ASP.Net检测到有潜在危险的Request.Form值

前两天公司一哥们遇到了这个问题,记录一下解决方法:

ASP.NET 2.0
方案一:将aspx文件中的page项添加ValidateRequest=”false”

  <%@ Page ValidateRequest="false"  Language="C#" AutoEventWireup="true" CodeFile="xxx.aspx.cs" Inherits="xxx.xxx" %>  

方案二:修改web.config配置文件(全局有效,慎用)

  <system.web> 
      <pages validateRequest="false"></pages>   
  </system.web> 

ASP.NET 4.0
方案一:修改web.config配置文件(全局有效,慎用)

  <system.web>
      <httpRuntime requestValidationMode="2.0" />
      <pages validateRequest="false"></pages>
  </system.web>

ASP.NET MVC
方案一:修改web.config配置文件(全局有效,慎用)
修改web.config配置文件(全局有效,慎用)

  <system.web>
      <httpRuntime requestValidationMode="2.0" />
  </system.web>

然后修改控制器

[HttpPost]
[ValidateInput(false)]
public ActionResult XXX(xxx xxx)
{
}

CSharp程序设置自动启动

using System;
using System.Text;
using Microsoft.Win32;

namespace GPJJ
{
    class XWin32Utils
    {
        private const String KEY_PATH = "SOFTWARE\\MICROSOFT\\WINDOWS\\CURRENTVERSION\\RUN";
        private const String VALUE_NAME = "GPJJEXE";

        public static bool isAutoRun()
        {
            RegistryKey key = Registry.LocalMachine;
            RegistryKey autorun = key.OpenSubKey(KEY_PATH, true);
            Object o = autorun.GetValue(VALUE_NAME);
            autorun.Close();

            if(o==null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        public static void SetAutoRun(String exePath)
        {
            RegistryKey key = Registry.LocalMachine;
            RegistryKey autorun = key.OpenSubKey(KEY_PATH, true);

            autorun.SetValue(VALUE_NAME, exePath, RegistryValueKind.String);
        }

        public static void RemoveAutoRun()
        {
            if(isAutoRun())
            {
                RegistryKey key = Registry.LocalMachine;
                RegistryKey autorun = key.OpenSubKey(KEY_PATH, true);
                autorun.DeleteValue(VALUE_NAME);
            }
        }
    }
}

Winform多行标题TabControl

今天写示例程序的时候,遇到了需要多行标题TabControl的情况。
整体流程很简单,就是将标题拆分,然后根据行数和最大行宽设置每一Page标题的高度及宽度即可。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace UITabControlTest
{
    public partial class SubForm : Form
    {
        private Dictionary<TabPage, TabPageInfo> allTabMap = new Dictionary<TabPage, TabPageInfo>();

        public SubForm()
        {
            InitializeComponent();
            tabMain.DrawMode = TabDrawMode.OwnerDrawFixed;
        }

        private void SubForm_Load(object sender, EventArgs e)
        {
            tabPage1.Text = "line1\nline2\nline3\nline4\nlin5";
            tabPage2.Text = "line1\nline2\nline3\nline4";
            tabPage3.Text = "line1\nline2\nline3";
            tabPage4.Text = "line1\nline2";

            int lineNum = 0;
            foreach (TabPage tab in this.tabMain.TabPages)
            {
                TabPageInfo pInfo = new TabPageInfo(tab.Text,"\n");
                allTabMap.Add(tab, pInfo);
                lineNum = lineNum>pInfo.LineNum?lineNum:pInfo.LineNum;
            }

            foreach (TabPage tab in this.tabMain.TabPages)
            {
                TabPageInfo pInfo = allTabMap[tab];
                tab.Text = pInfo.MaxLine;
            }

            //some thing is wrong, the font height is 14, the padding height is around 9, why?
            tabMain.Padding = new Point(0, Convert.ToInt32(tabMain.Font.Height * (lineNum - 1) * 0.65));
        }

        private void tabMain_DrawItem(object sender, DrawItemEventArgs e)
        {
            TabControl tabControl = (TabControl)sender;
            TabPage currentTab = tabControl.TabPages[e.Index];
            TabPageInfo info = allTabMap[currentTab];
            string tabText = info.AllLine;
            
            StringFormat sf = new StringFormat();
            sf.Alignment = StringAlignment.Center;
            sf.LineAlignment = StringAlignment.Center;
            RectangleF tabRect = (RectangleF)e.Bounds;
            RectangleF textRect = tabRect;
            if (e.Index == tabControl.SelectedIndex)
            {
                tabRect.Inflate(1, 1);
            }

            Graphics g = e.Graphics;
            g.Clip = new Region(tabRect);
            g.Clear(Control.DefaultBackColor);
            g.ResetClip();
            g.DrawString(tabText, e.Font, SystemBrushes.ControlText, textRect, sf);
        }
    }

    class TabPageInfo
    {
        public int LineNum
        {
            get
            {
                return nLineNum;
            }
        }

        public String MaxLine
        {
            get
            {
                //prevent auto wrap
                return szMaxLine+"  ";
            }
        }

        public String getLine(int index)
        {
            if (index < nLineNum)
            { 
                return szLines[index];
            }
            else
            {
                return "";
            }
        }

        public String AllLine
        {
            get
            {
                return szAllLine;
            }
        }

        private int nLineNum = 0;
        private String[] szLines;
        private String szAllLine;
        private String szMaxLine;

        public TabPageInfo(String pageTitle, String splitString)
        {
            szAllLine = pageTitle.Replace(splitString, "\n");
            String [] separators = new String[]{splitString};
            szLines = pageTitle.Split(separators,StringSplitOptions.RemoveEmptyEntries);
            nLineNum = szLines.Length;

            int nMaxLineWidth = 0;
            foreach(String line in szLines)
            {
                if (nMaxLineWidth < line.Length)
                {
                    nMaxLineWidth = line.Length;
                    szMaxLine = line;
                }
            }
        }
    }
}

IIS开启程序集绑定日志

最近,将一个AnyCPU+Win32的程序,调整到了x64架构,但一直各种绑定失败。
IIS7一直提示要开启程序就绑定日志:

警告: 程序集绑定日志记录被关闭。
要启用程序集绑定失败日志记录,请将注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD)设置为 1。
注意: 会有一些与程序集绑定失败日志记录关联的性能损失。
要关闭此功能,请移除注册表值 [HKLM\Software\Microsoft\Fusion!EnableLog]。

好吧,命令行搞定

reg add HKLM\software\microsoft\fusion /v Enablelog /t REG_DWORD /d 1

然后,IIS7仍然坚持不懈的提示绑定失败。提示dll格式不正确。
弄了一个多小时,发现应用程序池的“Enable 32-Bit Applications”选项打开了,晕死。
关闭之,搞定!!!

PS:
按网上的说法,Fuslogvw.exe可以查看绑定失败的日志。但我打开后没有哦,以后再试试看。

CSharp抓取JSON网页内容

    using Newtonsoft.Json;
    using DaZhongDianPing.JsonBeans;

    class JsonCrawler
    {
        private PhaseResultBean PhaseJson(Uri uri, String szResultPath, String szErrorPath)
        {
            PhaseResultBean result = new PhaseResultBean();

            try
            {
                //取回网页
                WebClient client = new WebClient();
                client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
                Byte[] pageData = client.DownloadData(uri);
                string pageHtml = Encoding.UTF8.GetString(pageData);
                JsonBeans.TopShopsBean topShops = JsonConvert.DeserializeObject<JsonBeans.TopShopsBean>(pageHtml);

                //分析Json
                int len = topShops.ShopBeans.Length;
                result.total = len;

                foreach (ShopBean shop in topShops.ShopBeans)
                {
                    try
                    {
                        String szTitle = shop.FilterFullName;
                        if (szTitle != null) szTitle = szTitle.Replace("\r\n", "-");
                        String szStar = shop.ShopPowerTitle;
                        String szMeanPrice = shop.AvgPrice.ToString();
                        String szRegionName = shop.MainRegionName;
                        String szAddress = shop.Address;
                        if (szAddress != null) szAddress.Replace(",", "-");

                        String szTaste = shop.RefinedScore1;
                        String szEvn = shop.RefinedScore2;
                        String szService = shop.RefinedScore3;

                        //将获取的内容写入文本
                        using (StreamWriter sw = new StreamWriter(szResultPath, true))
                        {
                            sw.WriteLine(szTitle + "," + szStar + "," + szMeanPrice + "," + szRegionName + "," + szAddress + "," + szTaste + "," + szEvn + "," + szService);
                        }

                        result.successed += 1;
                    }
                    catch (Exception Ex)
                    {
                        using (StreamWriter sw = new StreamWriter(szErrorPath, true))
                        {
                            sw.WriteLine(Ex.Message);
                        } 
                        result.failed += 1;
                    }
                }
            }
            catch (WebException webEx)
            {
                using (StreamWriter sw = new StreamWriter(szErrorPath, true))
                {
                    sw.WriteLine(webEx.Message);
                }
                result.bSuccess = false;
            }

            return result;
        }
    }

    class PhaseResultBean
    {
        public Boolean bSuccess;
        public int total;
        public int successed;
        public int failed;
    }

    public enum JsonEnginType
    {
        JsonEngin_Newtonsoft
    }

    internal class ShopBean
    {

        [JsonProperty("addDate")]
        public string AddDate { get; set; }

        [JsonProperty("addUser")]
        public object AddUser { get; set; }

        [JsonProperty("addUserName")]
        public object AddUserName { get; set; }

        [JsonProperty("address")]
        public string Address { get; set; }

        [JsonProperty("altName")]
        public string AltName { get; set; }

        [JsonProperty("avgPrice")]
        public int AvgPrice { get; set; }

        [JsonProperty("branchName")]
        public string BranchName { get; set; }

        [JsonProperty("branchTotal")]
        public int BranchTotal { get; set; }

        [JsonProperty("businessHours")]
        public string BusinessHours { get; set; }

        [JsonProperty("canSendSms")]
        public object CanSendSms { get; set; }

        [JsonProperty("categoryId")]
        public int CategoryId { get; set; }

        [JsonProperty("cityId")]
        public int CityId { get; set; }

        [JsonProperty("crossRoad")]
        public string CrossRoad { get; set; }

        [JsonProperty("defaultPic")]
        public string DefaultPic { get; set; }

        [JsonProperty("defaultPicBig")]
        public object DefaultPicBig { get; set; }

        [JsonProperty("dishTagList")]
        public string[][] DishTagList { get; set; }

        [JsonProperty("dishTags")]
        public string DishTags { get; set; }

        [JsonProperty("district")]
        public int District { get; set; }

        [JsonProperty("districtName")]
        public object DistrictName { get; set; }

        [JsonProperty("filterFullAdress")]
        public string FilterFullAdress { get; set; }

        [JsonProperty("filterFullName")]
        public string FilterFullName { get; set; }

        [JsonProperty("firstReviewId")]
        public int FirstReviewId { get; set; }

        [JsonProperty("firstUserFace")]
        public object FirstUserFace { get; set; }

        [JsonProperty("firstUserNickName")]
        public object FirstUserNickName { get; set; }

        [JsonProperty("fullAdress")]
        public string FullAdress { get; set; }

        [JsonProperty("fullName")]
        public string FullName { get; set; }

        [JsonProperty("glat")]
        public object Glat { get; set; }

        [JsonProperty("glng")]
        public object Glng { get; set; }

        [JsonProperty("groupFlag")]
        public object GroupFlag { get; set; }

        [JsonProperty("hasStaticMap")]
        public object HasStaticMap { get; set; }

        [JsonProperty("hits")]
        public int Hits { get; set; }

        [JsonProperty("isUserCanUpdate")]
        public object IsUserCanUpdate { get; set; }

        [JsonProperty("lastDate")]
        public string LastDate { get; set; }

        [JsonProperty("lastIp")]
        public object LastIp { get; set; }

        [JsonProperty("lastUser")]
        public object LastUser { get; set; }

        [JsonProperty("lastUserName")]
        public object LastUserName { get; set; }

        [JsonProperty("mainCategoryId")]
        public int MainCategoryId { get; set; }

        [JsonProperty("mainCategoryName")]
        public object MainCategoryName { get; set; }

        [JsonProperty("mainRegionId")]
        public int MainRegionId { get; set; }

        [JsonProperty("mainRegionName")]
        public string MainRegionName { get; set; }

        [JsonProperty("minUserMana")]
        public object MinUserMana { get; set; }

        [JsonProperty("monthlyHits")]
        public int MonthlyHits { get; set; }

        [JsonProperty("nearByTags")]
        public object NearByTags { get; set; }

        [JsonProperty("nearbyShops")]
        public object NearbyShops { get; set; }

        [JsonProperty("oldChainId")]
        public object OldChainId { get; set; }

        [JsonProperty("phoneNo")]
        public string PhoneNo { get; set; }

        [JsonProperty("phoneNo2")]
        public string PhoneNo2 { get; set; }

        [JsonProperty("picTotal")]
        public int PicTotal { get; set; }

        [JsonProperty("popularity")]
        public int Popularity { get; set; }

        [JsonProperty("power")]
        public int Power { get; set; }

        [JsonProperty("prevWeeklyHits")]
        public object PrevWeeklyHits { get; set; }

        [JsonProperty("priceInfo")]
        public object PriceInfo { get; set; }

        [JsonProperty("priceLevel")]
        public int PriceLevel { get; set; }

        [JsonProperty("primaryTag")]
        public string PrimaryTag { get; set; }

        [JsonProperty("promoId")]
        public int PromoId { get; set; }

        [JsonProperty("publicTransit")]
        public string PublicTransit { get; set; }

        [JsonProperty("refinedScore1")]
        public string RefinedScore1 { get; set; }

        [JsonProperty("refinedScore2")]
        public string RefinedScore2 { get; set; }

        [JsonProperty("refinedScore3")]
        public string RefinedScore3 { get; set; }

        [JsonProperty("regionId")]
        public int RegionId { get; set; }

        [JsonProperty("score")]
        public int Score { get; set; }

        [JsonProperty("score1")]
        public int Score1 { get; set; }

        [JsonProperty("score2")]
        public int Score2 { get; set; }

        [JsonProperty("score3")]
        public int Score3 { get; set; }

        [JsonProperty("score4")]
        public int Score4 { get; set; }

        [JsonProperty("searchKeyWord")]
        public object SearchKeyWord { get; set; }

        [JsonProperty("searchName")]
        public object SearchName { get; set; }

        [JsonProperty("shopGroupId")]
        public int ShopGroupId { get; set; }

        [JsonProperty("shopId")]
        public int ShopId { get; set; }

        [JsonProperty("shopName")]
        public string ShopName { get; set; }

        [JsonProperty("shopPower")]
        public int ShopPower { get; set; }

        [JsonProperty("shopPowerTitle")]
        public string ShopPowerTitle { get; set; }

        [JsonProperty("shopTagList")]
        public string[][] ShopTagList { get; set; }

        [JsonProperty("shopTags")]
        public string ShopTags { get; set; }

        [JsonProperty("shopTotalName")]
        public string ShopTotalName { get; set; }

        [JsonProperty("shopType")]
        public int ShopType { get; set; }

        [JsonProperty("similarShops")]
        public object SimilarShops { get; set; }

        [JsonProperty("suggestGA")]
        public object SuggestGA { get; set; }

        [JsonProperty("suggestReason")]
        public object SuggestReason { get; set; }

        [JsonProperty("todayHits")]
        public object TodayHits { get; set; }

        [JsonProperty("voteTotal")]
        public int VoteTotal { get; set; }

        [JsonProperty("webSite")]
        public object WebSite { get; set; }

        [JsonProperty("weeklyHits")]
        public int WeeklyHits { get; set; }

        [JsonProperty("wishTotal")]
        public object WishTotal { get; set; }

        [JsonProperty("writeUp")]
        public string WriteUp { get; set; }
    }

    internal class TopShopsBean
    {

        [JsonProperty("categoryId")]
        public int CategoryId { get; set; }

        [JsonProperty("cityId")]
        public int CityId { get; set; }

        [JsonProperty("maxResults")]
        public int MaxResults { get; set; }

        [JsonProperty("rankType")]
        public int RankType { get; set; }

        [JsonProperty("shopBeans")]
        public ShopBean[] ShopBeans { get; set; }

        [JsonProperty("shopType")]
        public int ShopType { get; set; }

        [JsonProperty("skipResults")]
        public int SkipResults { get; set; }
    }

CSharp抓取HTML网页内容

    using mshtml;
    using HtmlAgilityPack;

    class HTMLCrawler
    {
        private PhaseResultBean PhaseHtml(int index, Uri uri, String szResultPath, String szErrorPath, HTMLEnginType htmlEngin)
        {
            PhaseResultBean result = new PhaseResultBean();
            try
            {
                WebClient client = new WebClient();
                client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
                Byte[] pageData = client.DownloadData(uri);
                string pageHtml = Encoding.UTF8.GetString(pageData);
                if (checkSavePages.Checked)
                {
                    String szHtmlPath = XWin32.getExeParentPath() + index.ToString()+".html";
                    using (StreamWriter sw = new StreamWriter(szHtmlPath, true))
                    {
                        sw.WriteLine(pageHtml);
                    }
                }

                switch(htmlEngin)
                {
                    case HTMLEnginType.HTMLEngin_mshtml:
                        PhaseHtml_mshtml(pageHtml, szResultPath, szErrorPath, result);
                        break;
                    case HTMLEnginType.HTMLEngin_HtmlAgilityPack:
                        PhaseHtml_HtmlAgilityPack(pageHtml, szResultPath, szErrorPath, result);
                        break;
                }
            }
            catch (WebException webEx)
            {
                using (StreamWriter sw = new StreamWriter(szErrorPath, true))
                {
                    sw.WriteLine(webEx.Message);
                }
                result.bSuccess = false;
            }

            return result;
        }

        private void PhaseHtml_mshtml(String pageHtml, String szResultPath, String szErrorPath, PhaseResultBean result)
        {
            mshtml.HTMLDocument docObject = new mshtml.HTMLDocument();
            mshtml.IHTMLDocument2 doc2 = docObject as mshtml.IHTMLDocument2;
            doc2.write(pageHtml);
            doc2.close();

            mshtml.IHTMLDocument3 doc3 = docObject as mshtml.IHTMLDocument3;

            int len = doc3.getElementById("shop-all-list").children[0].children.length;
            result.total += len;

            foreach (IHTMLElement li in doc3.getElementById("shop-all-list").children[0].children)
            {
                try
                {
                    IHTMLElement title = li.children[1].children[0];
                    String szTitle = title.innerText;
                    if (szTitle != null) szTitle = szTitle.Replace("\r\n", "-");
                    IHTMLElement star = li.children[1].children[1].children[0];
                    String szStar = star.getAttribute("title");
                    IHTMLElement reviewNum = li.children[1].children[1].children[1];
                    String szReviewNum = reviewNum.innerText;
                    IHTMLElement meanPrice = li.children[1].children[1].children[3];
                    String szMeanPrice = meanPrice.innerText;
                    IHTMLElement category = li.children[1].children[2].children[0];
                    String szCategory = category.innerText;
                    IHTMLElement address = li.children[1].children[2].children[3];
                    String szAddress = address.innerText;
                    if (szAddress != null) szAddress.Replace(",", "-");

                    IHTMLElement taste = li.children[1].children[3].children[0];
                    String szTaste = taste.innerText;
                    IHTMLElement evn = li.children[1].children[3].children[1];
                    String szEvn = evn.innerText;
                    IHTMLElement service = li.children[1].children[3].children[2];
                    String szService = service.innerText;

                    //将获取的内容写入文本
                    using (StreamWriter sw = new StreamWriter(szResultPath, true))
                    {
                        sw.WriteLine(szTitle + "," + szStar + "," + szReviewNum + "," + szMeanPrice + "," + szCategory + "," + szAddress + "," + szTaste + "," + szEvn + "," + szService);
                    }
                }
                catch (Exception Ex)
                {
                    using (StreamWriter sw = new StreamWriter(szErrorPath, true))
                    {
                        sw.WriteLine(Ex.Message);
                    }

                    result.failed += 1;
                }

            }
        }

        private void PhaseHtml_HtmlAgilityPack(String pageHtml, String szResultPath, String szErrorPath, PhaseResultBean result)
        {
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(pageHtml);

            HtmlAgilityPack.HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("/html[1]/body[1]/div[4]/div[3]/div[1]/div[1]/div[2]/ul[1]/li");
            result.total += nodes.Count;

            foreach (HtmlAgilityPack.HtmlNode li in nodes)
            {
                try
                {
                    HtmlAgilityPack.HtmlNode titleA = li.SelectNodes("div[2]/div[1]/a[1]")[0];
                    HtmlAgilityPack.HtmlNode titleB = li.SelectNodes("div[2]/div[1]/a[2]") == null ? null : li.SelectNodes("div[2]/div[1]/a[2]")[0];
                    String szTitle = (titleA==null?"":titleA.InnerText) + "-" + (titleB == null ? "" : titleB.InnerText);
                    if (szTitle != null) szTitle = szTitle.Replace("\n", "");
                    if (szTitle != null) szTitle = szTitle.Replace(" ", "");

                    HtmlAgilityPack.HtmlNode star = li.SelectNodes("div[2]/div[2]/span[1]")[0];
                    String szStar = star.Attributes["title"].Value.ToString();

                    HtmlAgilityPack.HtmlNode reviewNum = li.SelectNodes("div[2]/div[2]/a[1]")[0];
                    String szReviewNum = reviewNum.InnerText;
                    if (szReviewNum != null) szReviewNum = szReviewNum.Replace("\n", "");
                    if (szReviewNum != null) szReviewNum = szReviewNum.Replace(" ", "");

                    HtmlAgilityPack.HtmlNode meanPrice = li.SelectNodes("div[2]/div[2]/a[2]")[0];
                    String szMeanPrice = meanPrice.InnerText;
                    if (szMeanPrice != null) szMeanPrice = szMeanPrice.Replace("\n", "");
                    if (szMeanPrice != null) szMeanPrice = szMeanPrice.Replace(" ", "");

                    HtmlAgilityPack.HtmlNode category = li.SelectNodes("div[2]/div[3]/a[1]")[0];
                    String szCategory = category.InnerText;

                    HtmlAgilityPack.HtmlNode addressA = li.SelectNodes("div[2]/div[3]/a[2]")[0];
                    HtmlAgilityPack.HtmlNode addressB = li.SelectNodes("div[2]/div[3]/span[1]")[0];
                    String szAddress = addressA.InnerText + "-" + addressB.InnerText;
                    if (szAddress != null) szAddress.Replace(",", "-");

                    HtmlAgilityPack.HtmlNode taste = li.SelectNodes("div[2]/span[1]/span[1]")[0];
                    String szTaste = taste.InnerText;
                    HtmlAgilityPack.HtmlNode evn = li.SelectNodes("div[2]/span[1]/span[2]")[0];
                    String szEvn = evn.InnerText;
                    HtmlAgilityPack.HtmlNode service = li.SelectNodes("div[2]/span[1]/span[3]")[0];
                    String szService = service.InnerText;

                    //将获取的内容写入文本
                    using (StreamWriter sw = new StreamWriter(szResultPath, true))
                    {
                        sw.WriteLine(szTitle + "," + szStar + "," + szReviewNum + "," + szMeanPrice + "," + szCategory + "," + szAddress + "," + szTaste + "," + szEvn + "," + szService);
                    }
                }
                catch (Exception Ex)
                {
                    using (StreamWriter sw = new StreamWriter(szErrorPath, true))
                    {
                        sw.WriteLine(Ex.Message);
                    }

                    result.failed += 1;
                }

            }
        }
    }

    class PhaseResultBean
    {
        public Boolean bSuccess;
        public int total;
        public int successed;
        public int failed;
    }

    public enum HTMLEnginType
    {
        HTMLEngin_mshtml,
        HTMLEngin_HtmlAgilityPack
    }

C#命令行打印PDF文档

1、使用Windows命令行
BAT Code

print /D:"\\COMPUTERNAME\打印机名" "PDF文件路径"

C# Code

ProcessStartInfo psInfo = new ProcessStartInfo();
psInfo.Verb = "Print"; // or "PrintTo"
psInfo.FileName = pdfFileName;
psInfo.Arguments = String.Format("/p /h \"{0}\" \"{1}\"", pdfFileName, printerName);
psInfo.WindowStyle = ProcessWindowStyle.Hidden;
psInfo.CreateNoWindow = true;
psInfo.UseShellExecute = true;
Process process = Process.Start(psInfo);

2、使用adobe命令行
BAT Code

#发送到默认打印机
AcroRd32.exe /s /o /h /p “PDF文件路径”
#发送到指定打印机
AcroRd32.exe /s /o /h /t “PDF文件路径” “打印机名” “驱动” “端口”

C# Code

ProcessStartInfo psInfo = new ProcessStartInfo();
psInfo.FileName = @"C:\Program Files\Adobe\Reader 9.0\Reader\AcroRd32.exe";
psInfo.Arguments = String.Format("/s /o /h /p{0}", pdfFileName);
psInfo.WindowStyle = ProcessWindowStyle.Hidden;
psInfo.CreateNoWindow = true;
psInfo.UseShellExecute = true;

Process p= Process.Start(psInfo);
p.WaitForInputIdle();
System.Threading.Thread.Sleep(3000);
if (false == p.CloseMainWindow())p.Kill();

3、使用gostscript命令行
BAT Code

gswin32c.exe -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -sDEVICE=ljet4 -sOutputFile="\\spool\打印机名称" "PDF文件路径"

C# Code

ProcessStartInfo psInfo = new ProcessStartInfo();
psInfo.Arguments = String.Format(" -dPrinted -dBATCH -dNOPAUSE -dNOSAFER -q -dNumCopies=1 -sDEVICE=ljet4 -sOutputFile=\"\\\\spool\\{0}\" \"{1}\"", printerName, pdfFileName);
psInfo.FileName = @"C:\Program Files\gs\gs8.70\bin\gswin32c.exe";
psInfo.UseShellExecute = false;

Process p= Process.Start(psInfo);
p.WaitForInputIdle();
System.Threading.Thread.Sleep(3000);
if (false == p.CloseMainWindow())p.Kill();

4、使用PrintDocument+第三方渲染插件(参考资料3)

PrintDocument pd = new PrintDocument();
pd.DocumentName = pdfName;
pd.PrinterSettings.PrinterName =printerName;
pd.PrinterSettings.PrintFileName = fileName;
pd.PrintController = new StandardPrintController();
pd.OriginAtMargins = false;
pd.PrintPage += new PrintPageEventHandler(this.pd_PrintPage);
pd.Print();

参考资料:
PDF: direct printing with .NET
How to Silently Print PDFs using Adobe Reader and C#
100% .NET component for rendering PDF documents

Windows服务程序访问NAS

由于服务程序授权与用户桌面授权互不影响,所以即使在用户桌面映射了NAS盘符,在Windows服务程序下仍然是不可以访问的。

一般来说有这样几种做法来访问NAS或共享盘:
1、加入域,通过“域用户认证”或“通过将NAS资源设置对某台计算机授权”来达到访问NAS的目的
2、不加域,在Windows中添加与NAS相同的用户名及密码,服务程序通过该用户名密码登录,可以访问NAS
3、不加域,通过调阅API的方式来获得访问NAS的权限
A、VC实现如下:

DWORD AcessNetDrtive(TCHAR* szRemotePath, TCHAR* szLocalDriver,  const TCHAR* szUsername, const TCHAR* szPassword)
{
	DWORD dwRetVal;
	DWORD dwFlags;

	NETRESOURCE nr;
	memset(&nr, 0, sizeof(NETRESOURCE));
	nr.dwScope = RESOURCE_GLOBALNET;
	nr.dwType = RESOURCETYPE_ANY;
	nr.lpLocalName = szLocalDriver;
	nr.lpRemoteName = szRemotePath;
	nr.lpProvider = NULL;

	//CONNECT_REDIRECT;CONNECT_UPDATE_PROFILE;
	dwFlags = 0;
	dwRetVal = WNetAddConnection2(&nr, szPassword, szUsername, dwFlags);

	retrun dwRetVal;
}

B、C#实现如下:

    public class NetworkDrive
    {
        public enum ResourceScope
        {
            RESOURCE_CONNECTED = 1,
            RESOURCE_GLOBALNET,
            RESOURCE_REMEMBERED,
            RESOURCE_RECENT,
            RESOURCE_CONTEXT
        }

        public enum ResourceType
        {
            RESOURCETYPE_ANY,
            RESOURCETYPE_DISK,
            RESOURCETYPE_PRINT,
            RESOURCETYPE_RESERVED
        }

        public enum ResourceUsage
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,
            RESOURCEUSAGE_CONTAINER = 0x00000002,
            RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
            RESOURCEUSAGE_SIBLING = 0x00000008,
            RESOURCEUSAGE_ATTACHED = 0x00000010,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        }

        public enum ResourceDisplayType
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN,
            RESOURCEDISPLAYTYPE_SERVER,
            RESOURCEDISPLAYTYPE_SHARE,
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        }

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public ResourceScope dwScope = 0;
            public ResourceType dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage dwUsage = 0;
            public string lpLocalName = null;
            public string lpRemoteName = null;
            public string lpComment = null;
            public string lpProvider = null;
        }

        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

        public static int MapNetworkDrive(string remotePath, string localDrive, string userName, string passWord)
        {
            NETRESOURCE myNetResource = new NETRESOURCE();
            myNetResource.lpLocalName = localDrive;
            myNetResource.lpRemoteName = remotePath;
            myNetResource.lpProvider = null;
            int result = WNetAddConnection2(myNetResource, passWord, userName, 0);
            return result;
        }
    }

IIS程序访问NAS

IIS程序访问NAS,一般有两种情况,加域和没加域
1、加域后,什么都好办,可以通过两种方式认证
A、采用域帐户认证
B、NAS资源可以直接授权给指定计算机访问

2、不加域,那一般有三种方式设置访问权限
A、通过指定程序的用户名和密码访问(这里指定的不是本地的用户名和密码,而是NAS的用户名和密码)
B、不指定用户名和密码,直接通过pass-through authentication方式访问,其规则为:
首先通过用户的真实id进行验证
如果用户没有授权,会尝试使用应用池的账户进行验证
如果应用池账号为NetworkService或LocalSystem,将使用计算机账号进行验证
采取这样的方式IIS会提出警告,因为IIS只有在运行之后,才知道能否访问NAS
C、通过代码实现

    //NAS访问封装类
    public class NetworkDrive
    {
        public enum ResourceScope
        {
            RESOURCE_CONNECTED = 1,
            RESOURCE_GLOBALNET,
            RESOURCE_REMEMBERED,
            RESOURCE_RECENT,
            RESOURCE_CONTEXT
        }

        public enum ResourceType
        {
            RESOURCETYPE_ANY,
            RESOURCETYPE_DISK,
            RESOURCETYPE_PRINT,
            RESOURCETYPE_RESERVED
        }

        public enum ResourceUsage
        {
            RESOURCEUSAGE_CONNECTABLE = 0x00000001,
            RESOURCEUSAGE_CONTAINER = 0x00000002,
            RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
            RESOURCEUSAGE_SIBLING = 0x00000008,
            RESOURCEUSAGE_ATTACHED = 0x00000010,
            RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
        }

        public enum ResourceDisplayType
        {
            RESOURCEDISPLAYTYPE_GENERIC,
            RESOURCEDISPLAYTYPE_DOMAIN,
            RESOURCEDISPLAYTYPE_SERVER,
            RESOURCEDISPLAYTYPE_SHARE,
            RESOURCEDISPLAYTYPE_FILE,
            RESOURCEDISPLAYTYPE_GROUP,
            RESOURCEDISPLAYTYPE_NETWORK,
            RESOURCEDISPLAYTYPE_ROOT,
            RESOURCEDISPLAYTYPE_SHAREADMIN,
            RESOURCEDISPLAYTYPE_DIRECTORY,
            RESOURCEDISPLAYTYPE_TREE,
            RESOURCEDISPLAYTYPE_NDSCONTAINER
        }

        [StructLayout(LayoutKind.Sequential)]
        private class NETRESOURCE
        {
            public ResourceScope dwScope = 0;
            public ResourceType dwType = 0;
            public ResourceDisplayType dwDisplayType = 0;
            public ResourceUsage dwUsage = 0;
            public string lpLocalName = null;
            public string lpRemoteName = null;
            public string lpComment = null;
            public string lpProvider = null;
        }

        [DllImport("mpr.dll")]
        private static extern int WNetAddConnection2(NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags);

        public static int MapNetworkDrive(string remotePath, string localDrive, string userName, string passWord)
        {
            NETRESOURCE myNetResource = new NETRESOURCE();
            myNetResource.lpLocalName = localDrive;
            myNetResource.lpRemoteName = remotePath;
            myNetResource.lpProvider = null;
            int result = WNetAddConnection2(myNetResource, passWord, userName, 0);
            return result;
        }
    }

    //调用示例
    NetworkDrive.MapNetworkDrive("NAS paht with ip", "Local Driver Letter", "user", "password");

参考资料:
What is “pass-through authentication” in IIS 7?

不支持一个STA线程上针对多个句柄的WaitAll

最近项目中用了COM控件,同时也用了多线程,在等待线程退出的地方,使用了

AutoResetEvent[] tEevents;
//...
WaitHandle.WaitAll(tEevents);

程序运行到这里,就会报错:

不支持一个STA线程上针对多个句柄的WaitAll

当时事情很急,将其调整为

AutoResetEvent[] tEevents;
//...
foreach(var tEvent in tEevents)
{
    tEvent.WaitOne();
}

就将这个问题绕了过去。

后来,在Stackoverflow上面,查了STA和MTA的区别。COM线程模型称为Apartment模型,分为STA和MTA两种。
STA(Single Thread Apartment)
STA是非线程安全的,常用于UI界面,其他线程要访问STA模式的COM组件,需要通过STA线程进行访问(其实就变成了单线程调用)
MTA(Multi Thread Apartment)
MTA是线程安全的,COM的程序员自己处理了并发的问题,其他线程可以直接访问COM组件

参考资料:
Could you explain STA and MTA?