如何在C#中读取域的TXT记录?

How do I read TXT records of a domain in C#?

我正在构建一个程序,并希望将最新版本号存储在我拥有的域的 TXT 记录中。拿到文字记录后我打算和现在的版本号做对比

我可以完成字符串比较部分,但我完全不知道您应该如何读取 DNS 记录。

如何在 C# 中执行此操作?

此存储库:MichaCo/DnsClient.NET 能够读取 DNS 端点中的 TXT 记录。

您可以使用助手 class 通过进行 dns 查找来检索它们。我写了一个 lil 脚本可以帮助您实现这一点:

using Util;
using System;

namespace DnsClient
{
    class Program
    {
        static void Main(string[] args)
        {
            var Domain = "www.contoso.com";
            var RequiredRecord = "MS=ms47806392";
            var RequiredValue = "ms47806392";
            var RequiredKey = "MS";
            // Check without trying to split the TXT Record
            if (CheckDnsRecordExists(Domain, RequiredRecord))
                Console.WriteLine($"Found TXT Record: {RequiredRecord}! :)");
            else
                Console.WriteLine("Not Found! :(");

            // Check by trying to split the TXT Record and checking for it's value
            if (CheckDnsRecordExists(Domain, RequiredKey, RequiredValue))
                Console.WriteLine($"Found Version {RequiredValue} of RecordID: {RequiredValue}! :)");
            else
                Console.WriteLine("Not Found! :(");

            Console.ReadKey();
        }
        private static bool CheckDnsRecordExists(string Domain, string RequiredRecord)
        {
            var Records = DnsInterop.GetTxtRecords(Domain);
            foreach (var record in Records)
            {
                if (record == RequiredRecord)
                {
                    return true;
                }
            }
            return false;
        }

        private static bool CheckDnsRecordExists(string Domain, string RequiredKey, string RequiredValue, char Separator = '=')
        {
            var Records = DnsInterop.GetTxtRecords(Domain);
            foreach (var record in Records)
            {
                var keyPair = record.Split(Separator);
                if (keyPair[0] != null && keyPair[1] != null)
                {
                    if (keyPair[0] == RequiredKey && keyPair[1] == RequiredValue)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}

@gordonmleigh 的这个示例 class,基于 Martin Liversage 的回答 ,可以帮助您检索给定特定域的 TXT 记录。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;

namespace Util
{
    /// <summary>
    /// Based on  (Martin Liversage)
    /// </summary>
    class DnsInterop
    {
        private const short DNS_TYPE_TEXT = 0x0010;
        private const int DNS_QUERY_STANDARD = 0x00000000;
        private const int DNS_ERROR_RCODE_NAME_ERROR = 9003;
        private const int DNS_INFO_NO_RECORDS = 9501;


        public static IEnumerable<string> GetTxtRecords(string domain)
        {
            var results = new List<string>();
            var queryResultsSet = IntPtr.Zero;
            DnsRecordTxt dnsRecord;

            try
            {
                // get all text records
                // pointer to results is returned in queryResultsSet
                var dnsStatus = DnsQuery(
                  domain,
                  DNS_TYPE_TEXT,
                  DNS_QUERY_STANDARD,
                  IntPtr.Zero,
                  ref queryResultsSet,
                  IntPtr.Zero
                );

                // return null if no records or DNS lookup failed
                if (dnsStatus == DNS_ERROR_RCODE_NAME_ERROR
                    || dnsStatus == DNS_INFO_NO_RECORDS)
                {
                    return null;
                }

                // throw an exception if other non success code
                if (dnsStatus != 0)
                    throw new Win32Exception(dnsStatus);

                // step through each result
                for (
                    var pointer = queryResultsSet; 
                    pointer != IntPtr.Zero; 
                    pointer = dnsRecord.pNext)
                {
                    dnsRecord = (DnsRecordTxt)
                        Marshal.PtrToStructure(pointer, typeof(DnsRecordTxt));

                    if (dnsRecord.wType == DNS_TYPE_TEXT)
                    {
                        var builder = new StringBuilder();

                        // pointer to array of pointers
                        // to each string that makes up the record
                        var stringArrayPointer = pointer + Marshal.OffsetOf(
                            typeof(DnsRecordTxt), "pStringArray").ToInt32();

                        // concatenate multiple strings in the case of long records
                        for (var i = 0; i < dnsRecord.dwStringCount; ++i)
                        {
                            var stringPointer = (IntPtr)Marshal.PtrToStructure(
                                stringArrayPointer, typeof(IntPtr));

                            builder.Append(Marshal.PtrToStringUni(stringPointer));
                            stringArrayPointer += IntPtr.Size;
                        }

                        results.Add(builder.ToString());
                    }
                }
            }
            finally
            {
                if (queryResultsSet != IntPtr.Zero)
                {
                    DnsRecordListFree(queryResultsSet, 
                        (int)DNS_FREE_TYPE.DnsFreeRecordList);
                }
            }

            return results;
        }


        [DllImport("Dnsapi.dll", EntryPoint = "DnsQuery_W", 
            ExactSpelling = true, CharSet = CharSet.Unicode, 
            SetLastError = true)]
        static extern int DnsQuery(string lpstrName, short wType, int options, 
            IntPtr pExtra, ref IntPtr ppQueryResultsSet, IntPtr pReserved);


        [DllImport("Dnsapi.dll")]
        static extern void DnsRecordListFree(IntPtr pRecordList, int freeType);


        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        struct DnsRecordTxt
        {
            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 string pStringArray;
        }


        enum DNS_FREE_TYPE
        {
            DnsFreeFlat = 0,
            DnsFreeRecordList = 1,
            DnsFreeParsedMessageFields = 2
        }
    }
}

希望对您有所帮助!

我基于 DnsDig 项目创建了一个 DLL,它可以在任何 .net(vb、c#、forms、web. 等等)项目上使用

https://devselz.com/software/devselz_dnsdig_dns-txt-etc-query-domain-register.zip

下载 DLL,解压缩,并添加为项目的引用(如果网站位于 root/bin 文件夹中):

DnsDig.dll

nunit.framework.dll

(共126KB)

然后将此示例用作 ASP.Net 网站(vb.net 代码)

Imports DnsDig
Imports Heijden.DNS
Partial Class lib_u_l_Default
    Inherits System.Web.UI.Page
    Public Resolver As Resolver
    Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
        Resolver = New Resolver
        Dim SW As New System.Diagnostics.Stopwatch
        SW.Start()
        Dim DNSResponse As Heijden.DNS.Response = Resolver.Query(Request.QueryString("d"), QType.TXT, QClass.ANY)
        SW.Stop()
        If DNSResponse.header.ANCOUNT > 0 Then
            For Each answerRR As AnswerRR In DNSResponse.Answers
                Response.Write("<br/>" & answerRR.ToString)
            Next
        End If
    End Sub

End Class

结果: https://yourwebsiteusingabovedlls.com/anyplacewhereabovecode/?d=goodyes.com

会写

goodyes.com。 3535 IN TXT“google-站点验证=IMw-tL0VWgMJbtcRgt_bu5UaVwpbNb94dvcOSObooa4” goodyes.com。 3535 IN TXT "v=spf1 include:_spf.buzondecorreo.com ~all"