2011年4月13日
By xsi640
分类: C#, WPF
随着计算机硬件设备的高速发展,很多用户的计算机上可能安装着好几块网卡,但是我们如何知道用户访问外网时所使用的网卡呢?
我先给出这两个win32函数
/// <summary>
/// 给出目的地的IP地址,返回网卡的接口索引
/// </summary>
/// <param name="DestAddr"></param>
/// <param name="BestIfIndex"></param>
/// <returns></returns>
[DllImport("iphlpapi.dll", CharSet = CharSet.Auto)]
public static extern int GetBestInterface(UInt32 DestAddr, out UInt32 BestIfIndex);
/// <summary>
/// 获得所有网卡信息
/// </summary>
/// <param name="pAdapterInfo"></param>
/// <param name="pBufOutLen"></param>
/// <returns></returns>
[DllImport("iphlpapi.dll", CharSet = CharSet.Ansi)]
public static extern int GetAdaptersInfo(IntPtr pAdapterInfo, ref Int64 pBufOutLen);
这下有思路了吧,先通过GetBestInterface函数获得网卡的接口索引,再通过GetAdaptersInfo获得该网卡的信息。
虽然,有了思路,不过实现起来对于没有做过C++开发的朋友还是比较困难的,在这里,我给出了代码大家看看吧。
IPHostEntry hostInfo = Dns.GetHostEntry("www.google.com");
IPAddress address = hostInfo.AddressList[0];//解析域名到IP地址
byte[] byteAddress = address.GetAddressBytes();
UInt32 ipaddr = BitConverter.ToUInt32(byteAddress, 0);//转换
UInt32 interfaceindex = 0;
GetBestInterface(ipaddr, out interfaceindex);//获得接口索引
Console.WriteLine("www.google.com的网卡接口索引:" + interfaceindex);
public static List<NetworkAdapter> GetAdapters()
{
List<NetworkAdapter> result = new List<NetworkAdapter>();
long structSize = Marshal.SizeOf(typeof(IP_ADAPTER_INFO));
IntPtr pArray = Marshal.AllocHGlobal(new IntPtr(structSize));
int ret = GetAdaptersInfo(pArray, ref structSize);//获得所有网卡信息
if (ret == ERROR_BUFFER_OVERFLOW)
{
pArray = Marshal.ReAllocHGlobal(pArray, new IntPtr(structSize));
ret = GetAdaptersInfo(pArray, ref structSize);
}
if (ret == 0)
{
IntPtr pEntry = pArray;
do
{
//当前网卡信息
IP_ADAPTER_INFO entry = (IP_ADAPTER_INFO)Marshal.PtrToStructure(pEntry, typeof(IP_ADAPTER_INFO));
NetworkAdapter networkAdapter = new NetworkAdapter();
networkAdapter.Index = entry.Index;//接口索引
string tmpString = string.Empty;
switch (entry.Type)
{
case MIB_IF_TYPE_ETHERNET: tmpString = "Ethernet"; break;
case MIB_IF_TYPE_TOKENRING: tmpString = "Token Ring"; break;
case MIB_IF_TYPE_FDDI: tmpString = "FDDI"; break;
case MIB_IF_TYPE_PPP: tmpString = "PPP"; break;
case MIB_IF_TYPE_LOOPBACK: tmpString = "Loopback"; break;
case MIB_IF_TYPE_SLIP: tmpString = "Slip"; break;
default: tmpString = "Other/Unknown"; break;
}
networkAdapter.AdapterType = tmpString;//网卡类型
networkAdapter.Name = entry.AdapterName;//网卡名称
networkAdapter.Description = entry.AdapterDescription;//网卡描述
networkAdapter.IsEnableDHCP = entry.DhcpEnabled == 1 ? true : false;//是否启用DHCP
if (entry.DhcpEnabled == 1)
{
networkAdapter.DHCPAddress = entry.DhcpServer.IpAddress.Address;
DateTime pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseObtained).ToLocalTime();
networkAdapter.DHCPLeaseObtained = pdatDate;//DHCP租约开始时间
pdatDate = new DateTime(1970, 1, 1).AddSeconds(entry.LeaseExpires).ToLocalTime();
networkAdapter.DHCPLeaseExpires = pdatDate;//DHCP租约结束时间
}
networkAdapter.IPAddress = entry.IpAddressList.IpAddress.Address;//IP地址
networkAdapter.SubNetMask = entry.IpAddressList.IpMask.Address;//子网掩码
networkAdapter.DefaultGateway = entry.GatewayList.IpAddress.Address;//网关
tmpString = string.Empty;
for (int i = 0; i < entry.AddressLength - 1; i++)
{
tmpString += string.Format("{0:X2}-", entry.Address[i]);
}
tmpString = string.Format("{0}{1:X2}", tmpString, entry.Address[entry.AddressLength - 1]);
networkAdapter.MACAddress = tmpString;//MAC地址
networkAdapter.HasWINS = entry.HaveWins;//是否有Wins
if (entry.HaveWins)
{
networkAdapter.PrimaryWINSServer = entry.PrimaryWinsServer.IpAddress.Address;//主Wins地址
networkAdapter.SecondaryWINSServer = entry.SecondaryWinsServer.IpAddress.Address;//辅Wins地址
}
result.Add(networkAdapter);
pEntry = entry.Next;
}
while (pEntry != IntPtr.Zero);
Marshal.FreeHGlobal(pArray);
}
else
{
Marshal.FreeHGlobal(pArray);
}
return result;
}
使用上面的方法就可以很容易的得到访问IP出口的网卡了。
代码下载
2011年4月1日
By xsi640
分类: C#, WPF
让.Net程序会说话,大家一定觉得是一件很困难的事情,不过,.Net Framework 4.0给我们带来了一个新的类库,System.Speech,可以让我们轻松的让计算机朗读出我们想要的内容。比如:一篇文章、一段说明,都不在话下。
首先添加System.Speech .Net类库引用
添加如下代码:
SpeechSynthesizer synthesizer = new SpeechSynthesizer();
synthesizer.Volume = 100; //音量 0~100
synthesizer.Rate = 0; //语速 -10~10
//同步朗读
synthesizer.Speak("欢迎光临.Net开发者博客!");
//异步朗读
synthesizer.SpeakAsync("欢迎光临.Net开发者博客!");
是不是很简单呢?呵呵,这个SpeechSynthesizer类不仅能读中文,英文也是很好滴。
2011年4月1日
By xsi640
分类: WPF
将win7玻璃效果扩展到窗体内部,我们知道,默认情况下,玻璃区域仅在标题栏和窗体边框,在窗体内部区域是不会绘制的,但是有一个简单的方法可以扩展玻璃区域到窗体内部,就是使用DWM‘s API。
代码如下:
MainWindow.xaml
<Window x:Class="WpfGlassDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="grid" Margin="20" Background="White">
<Button Content="Button" Width="200" Height="30"/>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
this.ExtendGlass(this.grid.Margin);
}
private void ExtendGlass(Thickness thikness)
{
try
{
int isGlassEnabled = 0;
//判断是否支持玻璃效果,即是否支持DWM's API
Win32.DwmIsCompositionEnabled(ref isGlassEnabled);
if (Environment.OSVersion.Version.Major > 5 && isGlassEnabled > 0)//是否是vista以上的操作系统
{
//获得窗体句柄
WindowInteropHelper helper = new WindowInteropHelper(this);
HwndSource mainWindowSrc = (HwndSource)HwndSource.FromHwnd(helper.Handle);
mainWindowSrc.CompositionTarget.BackgroundColor = Colors.Transparent;//背景色设成透明色
//获得桌面的dpi
System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(mainWindowSrc.Handle);
float dpiX = desktop.DpiX / 96;
float dpiY = desktop.DpiY / 96;
//设置边距
Win32.MARGINS margins = new Win32.MARGINS();
margins.cxLeftWidth = (int)(thikness.Left * dpiX);
margins.cxRightWidth = (int)(thikness.Right * dpiX);
margins.cyBottomHeight = (int)(thikness.Bottom * dpiY);
margins.cyTopHeight = (int)(thikness.Top * dpiY);
this.Background = Brushes.Transparent;
//将透明区域扩展到指定区域
int hr = Win32.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
}
else
{
this.Background = SystemColors.WindowBrush;
}
}
catch (DllNotFoundException)
{
}
}
}
Win32.cs
public static class Win32
{
[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
[DllImport("dwmapi.dll")]
public static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
[DllImport("dwmapi.dll")]
public extern static int DwmIsCompositionEnabled(ref int en);
}
效果:

代码下载
2011年4月1日
By xsi640
分类: C#
SqlBulkCopy是.Net提供的一个可以讲一个表复制到数据库的解决方案,其性能相比INSERT方式插入数据库要快得多,但是,由于实现机制,只适用于多条数据同时插入数据表,不适用于其他操作。
因为是表复制操作,必须有一个数据源,(目标即我们的SqlServer数据库)我们可以讲数据加载到DataTable或可使用IDataReader实例的对象中方可操作。
为了方便操作我们先生成了一个实体类,方便数据库操作。
class Person
{
public Guid PersonId { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
我们先看SqlCommand的数据插入代码:
static void InsertBySqlCommand()
{
//准备测试数据
List<Person> lists = new List<Person>();
for (int i = 0; i < 1000; i++)
{
Person p = new Person();
p.PersonId = Guid.NewGuid();
p.Age = i + 1;
p.Name = "姓名" + (i + 1);
p.Address = "地址" + (i + 1);
lists.Add(p);
}
Stopwatch sw = new Stopwatch();
sw.Start();
using (SqlConnection conn = new SqlConnection("Data Source=.;uid=sa;pwd=1234;Initial Catalog=demo"))
{
conn.Open();
foreach (Person p in lists)
{
//插入数据
using (SqlCommand cmd = new SqlCommand("INSERT INTO Person(PersonId,Name,Age,Address) VALUES(@PersonId,@Name,@Age,@Address) ", conn))
{
cmd.Parameters.Add(new SqlParameter("PersonId", p.PersonId));
cmd.Parameters.Add(new SqlParameter("Name", p.Name));
cmd.Parameters.Add(new SqlParameter("Age", p.Age));
cmd.Parameters.Add(new SqlParameter("Address", p.Address));
cmd.ExecuteNonQuery();
}
}
}
sw.Stop();
Console.WriteLine("SqlCommand方式插入1000条数据,用时" + sw.ElapsedMilliseconds);
}
下面是SqlBulkCopy的数据插入代码:
static void InsertBySqlBulkCopy()
{
//准备测试数据
List<Person> lists = new List<Person>();
for (int i = 0; i < 1000; i++)
{
Person p = new Person();
p.PersonId = Guid.NewGuid();
p.Age = i + 1;
p.Name = "姓名" + (i + 1);
p.Address = "地址" + (i + 1);
lists.Add(p);
}
Stopwatch sw = new Stopwatch();
sw.Start();
//将List转换到DataTable
DataTable dt = new DataTable();
dt.Columns.Add("PersonId", typeof(Guid));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Age", typeof(int));
dt.Columns.Add("Address", typeof(string));
foreach (Person p in lists)
{
DataRow row = dt.NewRow();
row["PersonId"] = p.PersonId;
row["Name"] = p.Name;
row["Age"] = p.Age;
row["Address"] = p.Address;
dt.Rows.Add(row);
}
using (SqlConnection conn = new SqlConnection("Data Source=.;uid=sa;pwd=1234;Initial Catalog=demo"))
{
conn.Open();
using (SqlBulkCopy sbc = new SqlBulkCopy(conn))
{
sbc.DestinationTableName = "Person";
sbc.WriteToServer(dt);//插入数据
}
}
sw.Stop();
Console.WriteLine("SqlBulkCopy方式插入1000条数据,用时" + sw.ElapsedMilliseconds);
}
运行结果:

从结果上很容易看出,SqlBulkCopy要比SqlCommand方式插入数据快得多。
代码下载
我们知道Json是一种特殊Javascript对象,介绍几个Json查看工具。
http://jsonviewer.codeplex.com/
.Net开发的Json查看器,可反编译查看源码,呵呵。
https://addons.mozilla.org/en-us/firefox/addon/jsonview/
火狐的Json查看器插件,可在火狐中打开Json内容查看
https://chrome.google.com/extensions/detail/chklaanhfefbnpoihckbnefhakgolnmc
谷歌浏览器的Json查看器插件,功能同上
http://jsonviewer.stack.hu/
在线的Json查看器,非常方便。
2011年3月24日
By xsi640
分类: C#
我们知道java有个转码工具native2ascii.exe可以实现将输入的中文字符转换成Unicode编码,如何在C#中实现此功能呢?下面会给出代码实现。
多说一句废话,什么时候会用到这个,主要是因为javascript中输出中文内容的时候,由于浏览器版本等问题,可能会带来中文内容显示成乱码,为了解决这个问题,我们可以直接在js输出时,直接输出Unicode编码形式的文本,浏览器会根据此文本直接转成中文字符输出到页面中。
public static string ConvertUnicode(string text)
{
if (string.IsNullOrWhiteSpace(text))
return string.Empty;
StringBuilder sb = new StringBuilder("");
char[] src = text.ToCharArray();
for (int i = 0; i < src.Length; i++)
{
byte[] bytes = Encoding.Unicode.GetBytes(src[i].ToString());
sb.Append(string.Format(@"\u{0}{1}", bytes[1].ToString("X2"), bytes[0].ToString("X2")));
}
return sb.ToString();
}
prototype在javascript中还是经常会用到的,如何理解这个属性呢?首先,他是一个属性,所有javascript对象都有这个属性,这个属性我们使用[类型].prototype来使用,返回值即该类型的原型。简单的说就是为对象的类返回原型的引用。
下面的例子中我们慢慢理解它。
//声明Test对象
function Test() {
};
//通过Test.prototype添加Test对象的getName方法
Test.prototype.getName = function(){
alert('123');
};
//实例化Test
var t = new Test();
//调用getName方法
t.getName();
输出:123
prototype实际上就是给我们提供了一个可以随时的动态的为对象添加方法或属性的一个桥梁。
2011年3月24日
By xsi640
分类: C#
Stopwatch,.Net中的秒表,可以精确的计算出时间间隔。先调用 Start 方法,然后调用 Stop 方法,最后使用 Elapsed 属性检查运行时间。
使用这个类,我们可以方便的查看程序的运行效率等问题。
Stopwatch watch = new Stopwatch();
watch.Start();
for (int i = 0; i < 1000; i++)
{
Thread.Sleep(1);
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds);
2011年3月18日
By xsi640
分类: C#
本文会提供GZip和Deflate两种数据压缩算法,都是使用了.Net内置的类库完成的,也没什么太多可解释的。
/// <summary>
/// GZip压缩
/// </summary>
public static class GZipCompressHelper
{
private const int BUFFER_LENGTH = 2048;
/// <summary>
/// GZip压缩字符串
/// </summary>
/// <param name="text">待压缩字符串</param>
/// <returns>已压缩字符串</returns>
public static string GZipCompress(string text)
{
string result = string.Empty;
byte[] data = Encoding.UTF8.GetBytes(text);
byte[] dData = GZipCompress(data);
result = Convert.ToBase64String(dData);
Array.Clear(dData, 0, dData.Length);
return result;
}
/// <summary>
/// GZip解压缩字符串
/// </summary>
/// <param name="text">待解压缩字符串</param>
/// <returns>已解压缩字符串</returns>
public static string GZipDeCompress(string text)
{
string result = string.Empty;
byte[] data = Convert.FromBase64String(text);
byte[] dData = GZipDeCompress(data);
result = Encoding.UTF8.GetString(dData);
Array.Clear(dData, 0, dData.Length);
return result;
}
/// <summary>
/// GZip压缩字节数组
/// </summary>
/// <param name="data">待压缩字节数组</param>
/// <returns>已压缩字节数组</returns>
public static byte[] GZipCompress(byte[] data)
{
byte[] result = null;
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true))
{
zip.Write(data, 0, data.Length);
zip.Flush();
}
result = ms.ToArray();
}
Array.Clear(data, 0, data.Length);
return result;
}
/// <summary>
/// GZip解压缩字节数组
/// </summary>
/// <param name="data">待解压缩字节数组</param>
/// <returns>已解压缩字节数组</returns>
public static byte[] GZipDeCompress(byte[] data)
{
byte[] result = null;
using (MemoryStream o = new MemoryStream())
{
using (MemoryStream ms = new MemoryStream(data))
{
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Flush();
int size = 0;
byte[] buffer = new byte[BUFFER_LENGTH];
while ((size = zip.Read(buffer, 0, buffer.Length)) > 0)
{
o.Write(buffer, 0, size);
}
}
}
result = o.ToArray();
}
return result;
}
}
/// <summary>
/// Deflate压缩
/// </summary>
public static class DeflateCompressHelper
{
private const int BUFFER_LENGTH = 2048;
/// <summary>
/// Deflate压缩字符串
/// </summary>
/// <param name="text">待压缩字符串</param>
/// <returns>已压缩字符串</returns>
public static string DeflateCompress(string text)
{
string result = string.Empty;
byte[] data = Encoding.UTF8.GetBytes(text);
byte[] dData = DeflateCompress(data);
result = Convert.ToBase64String(dData);
Array.Clear(dData, 0, dData.Length);
return result;
}
/// <summary>
/// Deflate解压缩字符串
/// </summary>
/// <param name="text">待解压缩字符串</param>
/// <returns>已解压缩字符串</returns>
public static string DeflateDeCompress(string text)
{
string result = string.Empty;
byte[] data = Convert.FromBase64String(text);
byte[] dData = DeflateDeCompress(data);
result = Encoding.UTF8.GetString(dData);
Array.Clear(dData, 0, dData.Length);
return result;
}
/// <summary>
/// Deflate压缩字节数组
/// </summary>
/// <param name="data">待压缩字节数组</param>
/// <returns>已压缩字节数组</returns>
public static byte[] DeflateCompress(byte[] data)
{
byte[] result = null;
using (MemoryStream ms = new MemoryStream())
{
using (DeflateStream deflate = new DeflateStream(ms, CompressionMode.Compress, true))
{
deflate.Write(data, 0, data.Length);
deflate.Flush();
}
result = ms.ToArray();
}
return result;
}
/// <summary>
/// Deflate解压缩字节数组
/// </summary>
/// <param name="data">待解压缩字节数组</param>
/// <returns>已解压缩字节数组</returns>
public static byte[] DeflateDeCompress(byte[] data)
{
byte[] result = null;
using (MemoryStream o = new MemoryStream())
{
using (MemoryStream ms = new MemoryStream(data))
{
using (DeflateStream deflate = new DeflateStream(ms, CompressionMode.Decompress))
{
deflate.Flush();
int size = 0;
byte[] buffer = new byte[BUFFER_LENGTH];
while ((size = deflate.Read(buffer, 0, buffer.Length)) > 0)
{
o.Write(buffer, 0, size);
}
}
}
result = o.ToArray();
}
return result;
}
}
2011年3月18日
By xsi640
分类: C#
一种简单的对称加密算法,不加解释了看代码就知道了,这里使用Rijndeal和DES对称加密算法。
/// <summary>
/// 对称加密/解密
/// </summary>
public static class EncryptHelper
{
private static readonly SymmetricAlgorithm _CryptoService;
private static readonly byte[] _Key;
private static readonly byte[] _IV;
private const int COUNT = 1024;
static EncryptHelper()
{
_CryptoService = new RijndaelManaged();//这里使用了Rijndael加密算法
//_CryptoService = new DESCryptoServiceProvider();//这里使用了DES加密算法
string sKey = "ads9a8H(@99ead80DSu09aduai)(SDn0a9sdi9";//长度固定为32位byte[]
string sIV = "SDS)(!OASODadkadka0-sd0-e0jsad0jajsd8(@";//长度固定为16位byte[]
//以下代码是判断Key和IV的长度 如果过长则截取 过短则补足 满足key为32位byte[] iv为16位byte[]
_CryptoService.GenerateKey();
int keyLength = _CryptoService.Key.Length;
if (sKey.Length > keyLength)
sKey = sKey.Substring(0, keyLength);
else if (sKey.Length < keyLength)
sKey = sKey.PadRight(keyLength, ' ');
_Key = ASCIIEncoding.ASCII.GetBytes(sKey);
_CryptoService.GenerateIV();
int ivLength = _CryptoService.IV.Length;
if (sIV.Length > ivLength)
sIV = sIV.Substring(0, ivLength);
else if (sIV.Length < ivLength)
sIV = sIV.PadRight(ivLength, ' ');
_IV = ASCIIEncoding.ASCII.GetBytes(sIV);
_CryptoService.Key = _Key;
_CryptoService.IV = _IV;
}
/// <summary>
/// 加密字符串
/// </summary>
/// <param name="text">明文字符串</param>
/// <returns>密文字符串</returns>
public static string Encrypt(string text)
{
string result = string.Empty;
if (string.IsNullOrEmpty(text))
return result;
byte[] data = Encoding.UTF8.GetBytes(text);
byte[] eData = Encrypt(data);
result = Convert.ToBase64String(eData);
Array.Clear(eData, 0, eData.Length);
return result;
}
/// <summary>
/// 解密字符串
/// </summary>
/// <param name="text">密文字符串</param>
/// <returns>明文字符串</returns>
public static string Decrypt(string text)
{
string result = string.Empty;
if (string.IsNullOrEmpty(text))
return result;
byte[] data = Convert.FromBase64String(text);
byte[] eData = Decrypt(data);
result = Encoding.UTF8.GetString(eData);
Array.Clear(eData, 0, eData.Length);
return result;
}
/// <summary>
/// 加密字节
/// </summary>
/// <param name="data">明文</param>
/// <param name="isClearData">加密后是否清除明文里面的数据</param>
/// <returns>密文</returns>
public static byte[] Encrypt(byte[] data, bool isClearData = true)
{
byte[] result = null;
using (MemoryStream ms = new MemoryStream())
{
using (ICryptoTransform encrypto = _CryptoService.CreateEncryptor())
{
using (CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
}
}
result = ms.ToArray();
}
if (isClearData)
Array.Clear(data, 0, data.Length);
return result;
}
/// <summary>
/// 解密字节
/// </summary>
/// <param name="data">密文</param>
/// <param name="isClearData">解密后是否清除密文里面的数据</param>
/// <returns>明文</returns>
public static byte[] Decrypt(byte[] data, bool isClearData = true)
{
byte[] result = null;
using (MemoryStream o = new MemoryStream())
{
using (MemoryStream ms = new MemoryStream(data, 0, data.Length))
{
using (ICryptoTransform encrypto = _CryptoService.CreateDecryptor())
{
using (CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read))
{
cs.Flush();
int size = 0;
byte[] buffer = new byte[COUNT];
while ((size = cs.Read(buffer, 0, buffer.Length)) > 0)
{
o.Write(buffer, 0, size);
}
}
}
}
result = o.ToArray();
}
if (isClearData)
Array.Clear(data, 0, data.Length);
return result;
}
}