
为什么要做这个工具呢,其实网上有很多域名注册查询,但我需要把查询出的数据保存到数据库。之前单线程查询速度很慢,改为多线程后快了很多,界面是用WPF做的
前台代码
<Window x:Class="DomainTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DomainTool"
xmlns:c="clr-namespace:FYJ.Winui.Controls;assembly=FYJ.Winui"
Title="域名查询工具@http://kecq.com" Height="400" Width="720">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="Margin" Value="5,0,0,0"></Setter>
</Style>
<Style TargetType="c:TextBoxEx">
<Setter Property="Height" Value="24"></Setter>
<Setter Property="Margin" Value="5,0,0,0"></Setter>
</Style>
<Style TargetType="c:ComboBoxEx">
<Setter Property="Height" Value="24"></Setter>
<Setter Property="Margin" Value="5,0,0,0"></Setter>
</Style>
<Style TargetType="c:CheckBoxEx">
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="Margin" Value="5,0,0,0"></Setter>
</Style>
<Style TargetType="Button">
<Setter Property="Margin" Value="5,0,0,0"></Setter>
</Style>
<local:ListViewItemColorConvert x:Key="itemConvert"></local:ListViewItemColorConvert>
</Window.Resources>
<DockPanel>
<WrapPanel DockPanel.Dock="Top" Margin="0,20,0,0">
<TextBlock Text="域名"></TextBlock>
<c:TextBoxEx Width="100" x:Name="txtDomain"></c:TextBoxEx>
<TextBlock Text="后缀"></TextBlock>
<c:ComboBoxEx Width="80" x:Name="comSuffix">
<ComboBoxItem IsSelected="True">.com</ComboBoxItem>
<ComboBoxItem>.cn</ComboBoxItem>
<ComboBoxItem>.net</ComboBoxItem>
<ComboBoxItem>.org</ComboBoxItem>
<ComboBoxItem>.cc</ComboBoxItem>
<ComboBoxItem>.me</ComboBoxItem>
<ComboBoxItem>.tv</ComboBoxItem>
<ComboBoxItem>.com.cn</ComboBoxItem>
<ComboBoxItem>.net.cn</ComboBoxItem>
</c:ComboBoxEx>
<TextBlock Text="长度"></TextBlock>
<c:TextBoxEx Text="1" Width="30" x:Name="txtMinLength"></c:TextBoxEx>
<TextBlock Text="-"></TextBlock>
<c:TextBoxEx Text="4" Width="30" x:Name="txtMaxLength"></c:TextBoxEx>
<TextBlock Text="分类"></TextBlock>
<c:ComboBoxEx Width="150" x:Name="txtCate">
</c:ComboBoxEx>
<TextBlock Text="状态"></TextBlock>
<c:ComboBoxEx Width="100" x:Name="comStatus">
</c:ComboBoxEx>
</WrapPanel>
<WrapPanel DockPanel.Dock="Top" Margin="0,10,0,10">
<c:CheckBoxEx Content="仅数据库" x:Name="chkDbOnly"></c:CheckBoxEx>
<Button Content="查询" Width="80" Margin="10,0,0,0" x:Name="btnQuery" Click="btnQuery_Click"></Button>
<Button Content="停止" Width="80" x:Name="btnStop" Click="btnStop_Click"></Button>
<Button Content="清空" Width="80" x:Name="btnClear" Click="btnClear_Click"></Button>
<TextBlock Text="域名是精确查询,如果输入了则会忽略掉一切其它查询条件" Foreground="#FFA29A9A" FontSize="11"></TextBlock>
</WrapPanel>
<Grid DockPanel.Dock="Bottom" Margin="0,10,0,10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="150"></ColumnDefinition>
</Grid.ColumnDefinitions>
<c:TextBlockEx Text="就绪" Name="txtState"></c:TextBlockEx>
<WrapPanel Grid.Column="1">
<TextBlock Text="数据库记录数:"></TextBlock>
<c:TextBlockEx Name="txtDbCount" Text="0"></c:TextBlockEx>
<TextBlock Text=" 网络查询:"></TextBlock>
<c:TextBlockEx Name="txtNetCount" Text="0"></c:TextBlockEx>
</WrapPanel>
<c:ProgressBarEx Grid.Column="2" Name="progressBar1" ValueChanged="progressBar1_ValueChanged"></c:ProgressBarEx>
</Grid>
<c:LogListBox Height="100" x:Name="logList1" DockPanel.Dock="Bottom" ></c:LogListBox>
<TabControl>
<TabItem Header="已注册(0)" x:Name="txtIsRegisteredCount">
<DataGrid x:Name="dataGrid1" AutoGenerateColumns="False" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header="域名">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Domain}" Background="{Binding Path=Color,Converter={StaticResource itemConvert}}" Foreground="Black" ></TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridHyperlinkColumn Binding="{Binding Path=Registered}" Width="150" Header="状态"/>
<DataGridTextColumn Binding="{Binding Path=RegisterDatetimeString}" Width="150" Header="注册时间"/>
<DataGridTextColumn Binding="{Binding Path=ExpireDatetimeString}" Width="150" Header="过期时间"/>
</DataGrid.Columns>
</DataGrid>
</TabItem>
<TabItem Header="未注册(0)" x:Name="txtNotRegisteredCount">
<DataGrid x:Name="dataGrid2" AutoGenerateColumns="False" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Domain}" Width="150" Header="域名"/>
</DataGrid.Columns>
</DataGrid>
</TabItem>
<TabItem Header="异常数(0)" x:Name="txtExceptionCount">
<DataGrid x:Name="dataGrid3" AutoGenerateColumns="False" IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Domain}" Width="150" Header="域名"/>
<DataGridTextColumn Binding="{Binding Message}" Width="300" Header="信息"/>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
</DockPanel>
<Window.TaskbarItemInfo>
<TaskbarItemInfo x:Name="taskbarItemInfo1">
</TaskbarItemInfo>
</Window.TaskbarItemInfo>
</Window>后台代码
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Shell;
namespace DomainTool
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
//线程数
private const int THREAD_COUNT = 10;
private FYJ.Data.IDbHelper db = FYJ.Data.DbFactory.GetIDbHelper("domain");
private IDomainQuery query = new NetcnQuery();
private ObservableCollection<DomainModel> list = new ObservableCollection<DomainModel>();
private ObservableCollection<DomainModel> notRegisterlist = new ObservableCollection<DomainModel>();
private ObservableCollection<object> exceptionlist = new ObservableCollection<object>();
private CancellationTokenSource cancelTokenSource = new CancellationTokenSource();
private ManualResetEvent mre = new ManualResetEvent(true); //初始化不等待
private AutoResetEvent eventFinished = new AutoResetEvent(false);
//已注册数
private int isRegisteredCount = 0;
//未注册数
private int notRegisterCount = 0;
//异常数
private int exceptionCount = 0;
//同步对象
private object sync = new object();
public MainWindow()
{
InitializeComponent();
}
#region 初始化
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.dataGrid1.ItemsSource = list;
this.dataGrid2.ItemsSource = notRegisterlist;
this.dataGrid3.ItemsSource = exceptionlist;
LoadCate();
LoadState();
this.btnStop.IsEnabled = false;
}
//加载域名类型
private void LoadCate()
{
List<object> list = new List<object>();
//list.Add(new { Text = "全部", Value = 0 });
//list.Add(new { Text = "纯英文", Value = 1 });
//list.Add(new { Text = "纯数字", Value = 2 });
//list.Add(new { Text = "非0开头纯数字", Value = 21 });
list.Add(new { Text = "非0开头带4纯数字", Value = 22 });
list.Add(new { Text = "非0开头不带4纯数字", Value = 23 });
//list.Add(new { Text = "中文拼音", Value = 7 });
//list.Add(new { Text = "英文单词", Value = 8 });
//list.Add(new { Text = "杂米", Value = 9 });
//list.Add(new { Text = "中文", Value = 10 });
this.txtCate.ItemsSource = list;
this.txtCate.SelectedValuePath = "Value";
this.txtCate.DisplayMemberPath = "Text";
this.txtCate.SelectedIndex = 0;
}
private void LoadState()
{
List<object> list = new List<object>();
list.Add(new { Text = "全部", Value = 0 });
list.Add(new { Text = "未注册", Value = 210 });
list.Add(new { Text = "已注册", Value = 211 });
this.comStatus.ItemsSource = list;
this.comStatus.SelectedValuePath = "Value";
this.comStatus.DisplayMemberPath = "Text";
this.comStatus.SelectedIndex = 0;
}
#endregion
private void InitValue()
{
this.btnQuery.IsEnabled = false;
this.btnStop.IsEnabled = true;
this.list.Clear();
this.logList1.Items.Clear();
this.progressBar1.Value = 0;
this.txtDbCount.Text = "0";
this.txtNetCount.Text = "0";
this.isRegisteredCount = 0;
this.notRegisterCount = 0;
this.exceptionCount = 0;
this.txtExceptionCount.Header = "异常数(0)";
}
private async void btnQuery_Click(object sender, RoutedEventArgs e)
{
try
{
if (this.txtMaxLength.Text.Trim() == "")
{
MessageBox.Show("请输入一个最大长度");
return;
}
int maxLength = Convert.ToInt32(this.txtMaxLength.Text.Trim());
if (maxLength < 2)
{
MessageBox.Show("最大长度必须大于1");
return;
}
if (maxLength > 6)
{
MessageBox.Show("最大长度暂时不能超过6");
return;
}
//初始化值
InitValue();
cancelTokenSource = new CancellationTokenSource();
string tableName = "tb_domain_" + this.comSuffix.Text.Substring(1);
string sql = "select Domain,RegisterDatetime,ExpireDatetime,Status from " + tableName + " where 1=1 ";
if (this.txtDomain.Text.Trim() != "")
{
sql += " and Domain = '" + this.txtDomain.Text.Trim() + this.comSuffix.Text + "'";
}
else
{
if (this.txtCate.SelectedValue.ToString() != "0")
{
sql += " and Cate=" + this.txtCate.SelectedValue;
}
if (this.txtMinLength.Text.Trim() != "")
{
sql += " and length(Domain)>=" + (Convert.ToInt32(this.txtMinLength.Text) + this.comSuffix.Text.Length);
}
if (this.txtMaxLength.Text.Trim() != "")
{
sql += " and length(Domain)<=" + (Convert.ToInt32(this.txtMaxLength.Text) + this.comSuffix.Text.Length);
}
if (this.comStatus.SelectedValue.ToString() != "0")
{
sql += " and Status=" + this.comStatus.SelectedValue;
}
}
this.txtState.Text = "正在查询数据库...";
DataTable dt = new DataTable();
await Task.Factory.StartNew(() =>
{
dt = db.GetDataTable(sql);
});
this.txtDbCount.Text = dt.Rows.Count + "";
this.txtState.Text = "正在展示数据库数据...";
foreach (DataRow dr in dt.Rows)
{
DomainModel model = new DomainModel();
model.Domain = dr["Domain"].ToString();
if (dt.Rows[0]["RegisterDatetime"].ToString() != "")
{
model.RegisterDatetime = Convert.ToDateTime(dt.Rows[0]["RegisterDatetime"]);
}
if (dt.Rows[0]["ExpireDatetime"].ToString() != "")
{
model.ExpireDatetime = Convert.ToDateTime(dt.Rows[0]["ExpireDatetime"]);
}
model.Status = Convert.ToInt32(dt.Rows[0]["Status"]);
this.dataGrid1.Dispatcher.Invoke((Action)(() =>
{
list.Add(model);
}));
}
//已被注册数
isRegisteredCount = list.Where(c => c.Status == 211).Count();
//未被注册数
notRegisterCount = list.Where(c => c.Status == 210).Count();
this.txtIsRegisteredCount.Header = "已注册(" + isRegisteredCount + ")";
this.txtNotRegisteredCount.Header = "未注册(" + notRegisterCount + ")";
if (this.chkDbOnly.IsChecked == true)
{
this.txtState.Text = "从数据库查询完毕,共查询到" + dt.Rows.Count + "条记录";
this.btnQuery.IsEnabled = true;
this.btnStop.IsEnabled = false;
return;
}
Queue<string> domains = new Queue<string>();
this.txtState.Text = "正在计算范围...";
await Task.Factory.StartNew(() =>
{
domains = GetDomainList();
this.progressBar1.Maximum = domains.Count - dt.Rows.Count;
});
List<Task> taskList = new List<Task>();
for (int i = 0; i < THREAD_COUNT; i++)
{
Task task = new Task(() =>
{
ThreadWork(domains);
}, cancelTokenSource.Token);
taskList.Add(task);
task.Start();
}
//等待所有线程完成
await Task.Factory.StartNew(() =>
{
Task.WaitAll(taskList.ToArray());
});
this.txtState.Text = "就绪";
}
catch (Exception ex)
{
this.txtState.Text = ex.Message;
}
this.btnStop.IsEnabled = false;
this.btnQuery.IsEnabled = true;
}
private void ThreadWork(Queue<string> domains)
{
if (cancelTokenSource.IsCancellationRequested)
{
this.logList1.AddErrorItem("线程" + Thread.CurrentThread.ManagedThreadId + "操作已被用户取消");
return;
}
mre.WaitOne();
Monitor.Enter(sync);
if (domains.Count == 0)
{
return;
}
string domain = domains.Dequeue();
Monitor.Exit(sync);
Monitor.Enter(sync);
this.txtState.Text = "线程" + Thread.CurrentThread.ManagedThreadId + "正在查询... " + (this.progressBar1.Value) + "/" + this.progressBar1.Maximum;
Monitor.Exit(sync);
try
{
//Thread.Sleep(300);
DomainModel model = this.QuerySingle(list, domain);
this.logList1.AddItem("线程" + Thread.CurrentThread.ManagedThreadId + "查询" + domain + "成功");
}
catch (Exception ex)
{
this.logList1.AddErrorItem("线程" + Thread.CurrentThread.ManagedThreadId + "查询" + domain + "失败:" + ex.Message);
Monitor.Enter(sync);
exceptionCount++;
this.Dispatcher.Invoke(() =>
{
this.exceptionlist.Add(new { Domain = domain, Message = ex.Message });
this.txtExceptionCount.Header = "异常数(" + exceptionCount + ")";
});
Monitor.Exit(sync);
}
if (domains.Count > 0)
{
ThreadWork(domains);
}
}
private Queue<string> GetDomainList()
{
Queue<string> list = new Queue<string>();
//查询单个域名
if (this.txtDomain.Text.Trim() != "")
{
string domain = this.txtDomain.Text.Trim() + this.comSuffix.Text;
list.Enqueue(domain);
}
else
{
int cate = Convert.ToInt32(this.txtCate.SelectedValue);
if (cate == 21 || cate == 22 || cate == 23)
{
string mintemp = "1";
for (int i = 1; i < Convert.ToInt32(this.txtMinLength.Text.Trim()); i++)
{
mintemp += "0";
}
string maxtemp = "";
for (int i = 0; i < Convert.ToInt32(this.txtMaxLength.Text.Trim()); i++)
{
maxtemp += "9";
}
for (int i = Convert.ToInt32(mintemp); i <= Convert.ToInt32(maxtemp); i++)
{
string domain = i + this.comSuffix.Text;
//域名是否存在不在这里判断 因为每次判断都要查询 效率太低了
//不限制4
if (cate == 21)
{
list.Enqueue(domain);
}
//带4
if (cate == 22)
{
if (i.ToString().Contains("4"))
{
list.Enqueue(domain);
}
}
//不带4
if (cate == 23)
{
if (!i.ToString().Contains("4"))
{
list.Enqueue(domain);
}
}
}
}
}
return list;
}
private DomainModel QuerySingle(ObservableCollection<DomainModel> list, string domain)
{
if (String.IsNullOrEmpty(domain))
{
throw new Exception("查询域名不能为空");
}
//如果数据库已包含该域名
DomainModel model = this.list.Where(c => c.Domain == domain).FirstOrDefault();
if (model != null)
{
return model;
}
model = query.Query(domain);
string tableName = "tb_domain_" + this.comSuffix.Text.Substring(1);
string sql = "insert into " + tableName + " (Domain,Suffix,RegisterDatetime,ExpireDatetime,Status,Whois,Cate,ADD_DATE,UPDATE_DATE) values (@Domain,@Suffix,@RegisterDatetime,@ExpireDatetime,@Status,@Whois,@Cate,@ADD_DATE,@UPDATE_DATE)";
db.ExecuteSql(sql
, db.CreateParameter("@Domain", model.Domain)
, db.CreateParameter("@Suffix", this.comSuffix.Text)
, db.CreateParameter("@RegisterDatetime", model.RegisterDatetime)
, db.CreateParameter("@ExpireDatetime", model.ExpireDatetime)
, db.CreateParameter("@Status", model.Status)
, db.CreateParameter("@Whois", model.Whois)
, db.CreateParameter("@Cate", this.txtCate.SelectedValue)
, db.CreateParameter("@ADD_DATE", DateTime.Now)
, db.CreateParameter("@UPDATE_DATE", DateTime.Now));
Monitor.Enter(sync);
if (model.Status == 211)
{
isRegisteredCount++;
this.Dispatcher.Invoke(() =>
{
this.txtIsRegisteredCount.Header = "已注册(" + isRegisteredCount + ")";
this.list.Add(model);
});
}
if (model.Status == 210)
{
notRegisterCount++;
this.Dispatcher.Invoke(() =>
{
this.txtNotRegisteredCount.Header = "未注册(" + notRegisterCount + ")";
this.notRegisterlist.Add(model);
});
}
int netCount = Convert.ToInt32(this.txtNetCount.Text);
this.txtNetCount.Text = (netCount + 1) + "";
this.progressBar1.Value = this.progressBar1.Value + 1;
Monitor.Exit(sync);
return model;
}
private void btnStop_Click(object sender, RoutedEventArgs e)
{
cancelTokenSource.Cancel();
this.btnQuery.IsEnabled = true;
}
private void btnClear_Click(object sender, RoutedEventArgs e)
{
this.Dispatcher.Invoke((Action)(() =>
{
list.Clear();
notRegisterlist.Clear();
exceptionlist.Clear();
}));
}
private void progressBar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
this.Dispatcher.Invoke((Action)(() =>
{
this.taskbarItemInfo1.ProgressState = TaskbarItemProgressState.Normal;
this.taskbarItemInfo1.ProgressValue = e.NewValue / this.progressBar1.Maximum;
if (e.NewValue == this.progressBar1.Maximum)
{
this.taskbarItemInfo1.ProgressState = TaskbarItemProgressState.None;
}
}));
}
}
}
珂珂的个人博客 - 一个程序猿的个人网站