Question

C’est la première fois que j’utilise C #, je suis donc totalement hors de mon élément. Mais je suis convaincu que les gens formidables de Stack Overflow peuvent m'aider! Je suis arrivé avec le code suivant (ci-dessous) basé sur d'autres morceaux de code que j'ai trouvés flottant sur Internet. Ce que j'essaie de faire est de rechercher tout le & texte; texte " Enregistrements DNS (TXT) d'un domaine donné. J'ai commencé simplement avec une application console dans Visual C # 2008 Express qui recherchait les enregistrements de google.com. Je m'inquiéterai de la personnalisation du domaine en fonction des paramètres de ligne de commande ultérieurement; pour l'instant je voudrais juste que cela fonctionne. Tous les outils de recherche DNS peuvent vous indiquer que google.com a cet enregistrement de texte DNS dans leur DNS:
v = spf1 comprend: _netblocks.google.com ip4: 216.73.93.70/31 ip4: 216.73.93.72/31 ~ all
Mais malheureusement, ce n'est pas ce que je reçois. Voici mon code:

namespace DnsUtils
{
    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Text;

    public class DnsTxt
    {
        [DllImport("dnsapi", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
        private static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)]ref string pszName, QueryTypes wType, QueryOptions options, int aipServers, ref IntPtr ppQueryResults, int pReserved);

        [DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern void DnsRecordListFree(IntPtr pRecordList, int FreeType);

        public static string[] GetTXTRecords(string domain)
        {
            IntPtr ptr1 = IntPtr.Zero;
            IntPtr ptr2 = IntPtr.Zero;
            TXTRecord recTxt;

            if (Environment.OSVersion.Platform != PlatformID.Win32NT)
            {
                throw new NotSupportedException();
            }

            ArrayList list1 = new ArrayList();
            UnicodeEncoding encoding = new UnicodeEncoding();

            int num1 = DnsTxt.DnsQuery(ref domain, QueryTypes.DNS_TYPE_TEXT, QueryOptions.DNS_QUERY_BYPASS_CACHE, 0, ref ptr1, 0);
            if (num1 != 0)
            {
                throw new Win32Exception(num1);
            }

            for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = recTxt.pNext)
            {
                recTxt = (TXTRecord)Marshal.PtrToStructure(ptr2, typeof(TXTRecord));
                if (recTxt.wType == 16)
                {
                    IntPtr pointerToAddressStringArray = Marshal.AllocHGlobal(IntPtr.Size);
                    IntPtr addressStringArray = Marshal.ReadIntPtr(pointerToAddressStringArray);

                    for (int i = 0; i < recTxt.dwStringCount; i++)
                    {
                        IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4);
                        int offset = 0;

                        ArrayList bytesList = new ArrayList();
                        byte newByte = Marshal.ReadByte(addressCharArray, offset++);
                        while (newByte != 0)
                        {
                            bytesList.Add(newByte);
                            newByte = Marshal.ReadByte(addressCharArray, offset++);
                        }
                        byte[] bytesArray = new byte[offset];
                        bytesList.CopyTo(bytesArray);
                        string textValue = encoding.GetString(bytesArray);

                        list1.Add(textValue);
                    }

                    Marshal.FreeHGlobal(pointerToAddressStringArray);
                }
            }

            DnsTxt.DnsRecordListFree(ptr2, 0);
            return (string[])list1.ToArray(typeof(string));
        }

        private enum QueryOptions
        {
            DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 1,
            DNS_QUERY_BYPASS_CACHE = 8,
            DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
            DNS_QUERY_NO_HOSTS_FILE = 0x40,
            DNS_QUERY_NO_LOCAL_NAME = 0x20,
            DNS_QUERY_NO_NETBT = 0x80,
            DNS_QUERY_NO_RECURSION = 4,
            DNS_QUERY_NO_WIRE_QUERY = 0x10,
            DNS_QUERY_RESERVED = -16777216,
            DNS_QUERY_RETURN_MESSAGE = 0x200,
            DNS_QUERY_STANDARD = 0,
            DNS_QUERY_TREAT_AS_FQDN = 0x1000,
            DNS_QUERY_USE_TCP_ONLY = 2,
            DNS_QUERY_WIRE_ONLY = 0x100
        }

        private enum QueryTypes
        {
            DNS_TYPE_TEXT = 16
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct TXTRecord
        {
            public IntPtr pNext;
            public string pName;
            public short wType;
            public short wDataLength;
            public int flags;
            public int dwTtl;
            public int dwReserved;
            public int dwStringCount;
            public IntPtr pStringArray;
        }

        static void Main(string[] args)
        {
            try
            {
                string[] s = DnsUtils.DnsTxt.GetTXTRecords("google.com");
                foreach (string st in s)
                {
                    Console.WriteLine("Value: {0}", st);
                }
            }
            catch (Win32Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.ReadLine();
        }
    }
}

Lorsque j'exécute ce code, il affiche Valeur:? . Maintenant, j'espère que cela signifie que la requête DNS a bien été obtenue et que les résultats ont été obtenus comme prévu, mais j'ai simplement foiré quelque chose dans la partie où il tente de convertir un IntPtr en un tableau de chaînes (car je suppose que c'est plus difficile déboguer l'ancien). Quoi qu'il en soit, avez des suggestions? Quelqu'un peut-il voir où je suis allé mal? Merci d'avance.

Était-ce utile?

La solution

Cette ligne me ressemble un peu:

IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4);

Il semblerait que vous lisiez les 4 premiers octets de la première entrée de chaîne de l’enregistrement TXT en tant que IntPtr. Je pense quelque chose comme:

string s = Marshal.PtrToStringAuto(recTxt.pStringArray);

vous obtiendrez la première entrée. Après cela, je pense à quelque chose comme:

IntPtr p = new IntPtr(recTxt.pStringArray.ToInt32() + sizeof(uint) * i);
string s = Marshal.PtrToStringAuto(p);

obtiendrait les restes.

Autres conseils

Comme alternative plus simple, vous pouvez éviter de traiter tous les interopérabilité COM en créant un nouveau processus nslookup et en analysant StandardOuput pour saisir ce dont vous avez besoin.

using System;
using System.Diagnostics;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var startInfo = new ProcessStartInfo("nslookup");
            startInfo.Arguments = "-type=TXT google.com";
            startInfo.RedirectStandardOutput = true;
            startInfo.UseShellExecute = false;
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;

            using (var cmd = Process.Start(startInfo))
            {
              // This is where you grab the output from nslookup.
                Console.WriteLine(cmd.StandardOutput.ReadToEnd());
            }
            Console.Read();
        }
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top