C# Https Soap Client

1、Soap Https Soap Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace IISSoapClientTest
{
    class Program
    {
        public static void HelloHttp(string url)
        {
            Hello h = new Hello(url);
            string ans = h.HelloWorld("C# http client");
            Console.WriteLine(ans);
            Console.WriteLine();
        }

        //同样的证书,IIS可以过,Tomcat过不去
        public static void HelloHttps(string url,String certPath)
        {
            X509CertificateCollection certs = new X509CertificateCollection();
            X509Certificate cert = X509Certificate.CreateFromCertFile(certPath);

            Hello h = new Hello(url);
            h.ClientCertificates.Add(cert);
            string ans = h.HelloWorld("C# https client");
            Console.WriteLine(ans);
            Console.WriteLine();
        }

        //绕过证书检查
        public static void HelloHttpsWithRemoteCertificateValidationCallback(string url)
        {
            //ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
            ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(RemoteCertificateValidationCallback);

            Hello h = new Hello(url);
            string ans = h.HelloWorld("C# https client");
            Console.WriteLine(ans);
            Console.WriteLine();
        }

        private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, 
            X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }  

        static void Main(string[] args)
        {
            //HelloHttp("http://127.0.0.1:80/Hello.asmx");
            //HelloHttps("https://127.0.0.1:443/Hello.asmx");
            //HelloHttpsWithRemoteCertificateValidationCallback("https://127.0.0.1:443/Hello.asmx");

            //HelloHttp("http://127.0.0.1:8080/SoapTest/services/HelloService");
            HelloHttps("https://127.0.0.1:8443/SoapTest/services/HelloService", @"D:\DiskE\Projects\VS2010\TestProjects\SSLSocket\myKeyStore.cer");
            //HelloHttpsWithRemoteCertificateValidationCallback("https://127.0.0.1:8443/SoapTest/services/HelloService");
        }
    }
}

C# Https Soap Server(IIS7)

1、首先准备一个p12格式的服务端证书
无论是购买,还是用openssl或java keytool生成自签名证书都可以

2、在IIS7的根目录,选中“安全性->根目录证书”,选择“导入”即可

3、如果显示证书链有问题,则在IE中导入CA证书就好了

4、在需要HTTPS的网站上,选择“绑定”,绑定类型为https,选择需要的证书

5、在客户端的IE中,导入CA证书就好了

SSLSocket C# Part1

1、SSLSocket Server

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace SSLSocket
{
    class SSLSocketServer
    {
        static X509Certificate serverCertificate = null;
        static String delimiter = "=========================================================";

        public static void RunServer(String ip,int port,String p12Path)
        {
            serverCertificate = new X509Certificate2(p12Path, "sslTestPwd");

            TcpListener listener = new TcpListener(IPAddress.Parse(ip), port);
            listener.Start();
            while (true)
            {
                try
                {
                    TcpClient client = listener.AcceptTcpClient();
                    ProcessClient(client);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex);
                }
            }
        }

        static void ProcessClient(TcpClient client)
        {
            SslStream sslStream = new SslStream(client.GetStream(), false);
            try
            {
                //sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls | SslProtocols.Ssl2 | SslProtocols.Ssl3 | SslProtocols.None, true);
                sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Ssl2 | SslProtocols.Ssl3, true);
                DisplaySecurityLevel(sslStream);
                DisplayCertificateInformation(sslStream);

                sslStream.ReadTimeout = 5000;
                sslStream.WriteTimeout = 5000;
                string messageData = ReadMessage(sslStream);
                Console.WriteLine(delimiter);
                Console.WriteLine("收到信息: {0}", messageData);
                Console.WriteLine(delimiter);
                //byte[] message = Encoding.UTF8.GetBytes("Hello from the server.");
                //Console.WriteLine("Sending hello message.");
                //sslStream.Write(message);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                sslStream.Close();
                client.Close();
                return;
            }
            finally
            {
                sslStream.Close();
                client.Close();
            }
        }

        static string ReadMessage(SslStream sslStream)
        {
            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                bytes = sslStream.Read(buffer, 0, buffer.Length);
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                if (messageData.ToString().IndexOf("") != -1)
                {
                    break;
                }
            }
            while (bytes != 0);

            return messageData.ToString();
        }

        static void DisplaySecurityLevel(SslStream stream)
        {
            Console.WriteLine(delimiter);
            Console.WriteLine("通讯协议: {0}", stream.SslProtocol);
            Console.WriteLine("加密算法: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
            Console.WriteLine("哈希算法: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
            Console.WriteLine("密钥交换算法: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
            Console.WriteLine(delimiter);
        }

        static void DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine(delimiter);
            Console.WriteLine("证书吊销列表检查: {0}", stream.CheckCertRevocationStatus);

            X509Certificate localCertificate = stream.LocalCertificate;
            if (stream.LocalCertificate != null)
            {
                Console.WriteLine("本地证书签发者: {0}", localCertificate.Subject);
                Console.WriteLine("本地证书有效期: {0}~{1}", localCertificate.GetEffectiveDateString(),
                    localCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("本地证书为空");
            }

            X509Certificate remoteCertificate = stream.RemoteCertificate;
            if (stream.RemoteCertificate != null)
            {
                Console.WriteLine("远程证书签发者: {0}", remoteCertificate.Subject);
                Console.WriteLine("远程证书有效期: {0}至{1}", remoteCertificate.GetEffectiveDateString(),
                    remoteCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("远程证书为空");
            }
            Console.WriteLine(delimiter);
        }

    }
}

2、SSLSocket Client

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;

namespace SSLSocketClient
{
    class SSLSocketClient
    {
        //回调函数验证证书
        public static bool ValidateServerCertificate(
              object sender,
              X509Certificate certificate,
              X509Chain chain,
              SslPolicyErrors sslPolicyErrors)
        {
            if (sslPolicyErrors == SslPolicyErrors.None)
            {
                return true;
            }

            if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateNameMismatch || sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
            {
                return true;
            }

            return false;
        }

        public static void SendMessage(string ip, int port,String certPath, String msg)
        {
            TcpClient client = new TcpClient(ip, port);
            SslStream sslStream = new SslStream(client.GetStream(),
                false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);

            X509CertificateCollection certs = new X509CertificateCollection();
            X509Certificate cert = X509Certificate.CreateFromCertFile(certPath);
            certs.Add(cert);

            try
            {
                sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.Tls, false);
                //sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.Ssl3, false);

                //sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.Ssl2, false);
                //sslStream.AuthenticateAsClient("AtlasTiger", certs, SslProtocols.None, false);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Authentication failed : " + e);
                client.Close();
                return;
            }

            byte[] messsage = Encoding.UTF8.GetBytes(msg);
            sslStream.Write(messsage);
            sslStream.Flush();

            client.Close();
        }
    }
}

指定WebBrowser控件的IE版本

1、假设你的程序用到了WebBrowser,程序名为XXX.exe,希望发布时指定WebBrowser的IE版本

2、在注册表指定的位置,新建名为XXX.exe的DWORD值,并按Browser Emulation的值,设置正确的IE版本即可。

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
或
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION

3、如果是在VS调试时,需要指定其版本,则要设置VS的程序名,而不是被调试程序的程序名

4、Browser Emulation

Value Description
11001 (0x2AF9) Internet Explorer 11. Webpages are displayed in IE11 edge mode, regardless of the declared !DOCTYPE directive. Failing to declare a !DOCTYPE directive causes the page to load in Quirks.
11000 (0x2AF8) IE11. Webpages containing standards-based !DOCTYPE directives are displayed in IE11 edge mode. Default value for IE11.
10001 (0x2711) Internet Explorer 10. Webpages are displayed in IE10 Standards mode, regardless of the !DOCTYPE directive.
10000 (0x02710) Internet Explorer 10. Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode. Default value for Internet Explorer 10.
9999 (0x270F) Windows Internet Explorer 9. Webpages are displayed in IE9 Standards mode, regardless of the declared !DOCTYPE directive. Failing to declare a !DOCTYPE directive causes the page to load in Quirks.
9000 (0x2328) Internet Explorer 9. Webpages containing standards-based !DOCTYPE directives are displayed in IE9 mode. Default value for Internet Explorer 9.
Important In Internet Explorer 10, Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode.
8888 (0x22B8) Webpages are displayed in IE8 Standards mode, regardless of the declared !DOCTYPE directive. Failing to declare a !DOCTYPE directive causes the page to load in Quirks.
8000 (0x1F40) Webpages containing standards-based !DOCTYPE directives are displayed in IE8 mode. Default value for Internet Explorer 8.
Important In Internet Explorer 10, Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode.
7000 (0x1B58) Webpages containing standards-based !DOCTYPE directives are displayed in IE7 Standards mode. Default value for applications hosting the WebBrowser Control.

参考:
MSDN

CS访问网络资源

using System.Runtime.InteropServices;
 
public class WNetHelper
{
	 [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")]
	 private static extern uint WNetAddConnection2(NetResource lpNetResource, string lpPassword, string lpUsername, uint dwFlags);
 
	 [DllImport("Mpr.dll", EntryPoint = "WNetCancelConnection2")]
	 private static extern uint WNetCancelConnection2(string lpName, uint dwFlags, bool fForce);
 
	 [StructLayout(LayoutKind.Sequential)]
	 public class NetResource
	 {
		  public int dwScope;
		  public int dwType;
		  public int dwDisplayType;
		  public int dwUsage;
		  public string lpLocalName;
		  public string lpRemoteName;
		  public string lpComment;
		  public string lpProvider;
	 }
 
	 public static uint WNetAddConnection(string username, string password, string remoteName, string localName)
	 {
		  NetResource netResource = new NetResource();
 
		  netResource.dwScope = 2;
		  netResource.dwType = 1;
		  netResource.dwDisplayType = 3;
		  netResource.dwUsage = 1;
		  netResource.lpLocalName = localName;
		  netResource.lpRemoteName = remoteName.TrimEnd('\\');
		  uint result = WNetAddConnection2(netResource, password, username, 0);
 
		  return result;
	 }
 
	 public static uint WNetCancelConnection(string name, uint flags, bool force)
	 {
		  uint nret = WNetCancelConnection2(name, flags, force);
		  return nret;
	 }
}

C#深度拷贝

如果类实现了序列化,那么先序列化再反序列化一下,
就得到了一个深度拷贝的对象啦

public static T DeepClone<T>(T obj)
{
    using (var ms = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(ms, obj);
        ms.Position = 0;
        return (T) formatter.Deserialize(ms);
    }
}

跨线程创建窗体的两种方法

1、利用新STA线程进行创建

//线程
private System.Threading.Thread th=null;

//创建线程
try
{
    th = new System.Threading.Thread((System.Threading.ThreadStart)delegate
    {
        Application.Run(new fmFreeChatClient(url));
    });

    th.SetApartmentState(ApartmentState.STA);
    th.Start();
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
}

2、用delegate

//在form中声明
#region 新建Form并显示
delegate void showForm(string url);
public void showMyForm(string url)
{
//新建窗体并显示
}
#endregion

//在线程中调用
Object[] objs = new Object[1];
objs[0]="hello";
this.Invoke(new showForm(showMyForm),objs);

C#调用cdll指针参数处理

1、API声明(包括**参数)

int GetTheLastErrorA(char **pcError);
int GetTheLastErrorW(wchar_t **pwError);

2、C#代码

using System.Runtime.InteropServices;

[DllImport("StringAW.dll", CallingConvention = CallingConvention.Winapi, 
CharSet = CharSet.Ansi, EntryPoint = "GetTheLastErrorA")]
extern static int GetTheLastErrorA(ref IntPtr a);

[DllImport("StringAW.dll", CallingConvention = CallingConvention.Winapi, 
CharSet = CharSet.Auto, EntryPoint = "GetTheLastErrorW")]
extern static int GetTheLastErrorW(ref IntPtr w);

IntPtr a = IntPtr.Zero;
GetTheLastErrorA(ref a);
String sa = Marshal.PtrToStringAnsi(a);
MessageBox.Show(sa);

IntPtr w = IntPtr.Zero;
GetTheLastErrorW(ref w);
String sw = Marshal.PtrToStringUni(w);
MessageBox.Show(sw);

汉化.net程序

1.首先是反编译

ildasm11.exe /ALL /VISIBILITY=PUB+PRI+FAM+ASM+FAA+FOA+PSC /UNICODE Target.dll /OUT=Target.il

2.打开Target.il
搜索ldstr,后面就是你所需要汉化的字符串

同时会遇到bytearray类型的字符串,这些字符串是以UNICODE的HEX方式存储的,将汉化后内容,同样转成UNICODE的HEX字符串存回去,同时记住要修改字体

3.去掉StrongName
将Target.il中publickkey字段删除

4.生成snk

sn.exe -k Target.snk

5.重新编译并增加StrongName

ILASM11.exe Target.il /dll /key:Target.snk /resource:Target.res /out:Target_cn.dll

6.验证

sn -v Target_cn.dll