2010年5月7日

IIS中加入piwik跟踪代码

好久没来写博了...
今天写一下如何在IIS中加入piwik跟踪代码。
背景:
•    piwik 开源php站点统计程序        http://piwik.org
•    HttpModule: http://www.cnblogs.com/stwyhm/archive/2006/08/09/471729.html
实现思路:通过HttpModule在aspx页面的body前加入统计代码。
代码实现:

1. 新建dll项目   

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO; 

namespace PiwikAnalytics
{
    /// 修改于网上流传的Google Analytics (https://www.google.com/analytics/) script    
    public class PiwikAnalyticsModule : IHttpModule
    {
        static string GoogleScript = string.Empty;
        HttpApplication application; 

        public void Dispose()
        {
            //context.BeginRequest -= new EventHandler(OnBeginRequest);
        } 

        public void Init(HttpApplication context)
        {
            context.BeginRequest += new EventHandler(OnBeginRequest);
            application = context;
        } 

        void OnBeginRequest(object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;
            //web.config中定义的站点字符串,后面会有介绍
            string sites = ConfigurationManager.AppSettings["PiwikAnalyticsSites"];
            //此处未进行异常处理,大家发布时记得加上哦~
            string[] siteArr = sites.Split(';');
            string siteid = "5";
            foreach (string site in siteArr)
            {
                if (application.Request.Url.OriginalString.ToLower().IndexOf(site.Split(',')[0]) > 0)
                {
                    siteid = site.Split(',')[1];
                }
            } 

            GoogleScript = @" <!-- Piwik -->
             <script type=""text/javascript"">
        var pkBaseURL = ((""https:"" == document.location.protocol) ? ""https://yourpiwik.com/piwik/"" : ""http://yourpiwik.com/piwik/"");
        document.write(unescape(""%3Cscript src='"" + pkBaseURL + ""piwik.js' type='text/javascript'%3E%3C/script%3E""));
    </script> 

    <script type=""text/javascript"">
        //try {          
            var piwikTracker = Piwik.getTracker(pkBaseURL + ""piwik.php"", " + siteid + @");           
            piwikTracker.trackPageView();
            piwikTracker.enableLinkTracking();
        //} catch (err) { }
    </script> 

    <noscript>
        <p>
            <img id=""img1"" src=""http://pm.taobao.ali.com/piwik/piwik.php?idsite="+siteid+@""" style=""border: 0"" alt="""" /></p>
    </noscript>
            <!-- End Piwik Tag -->"; 

            //这里需要针对ASPX页面进行拦截
            string[] temp = application.Request.CurrentExecutionFilePath.Split('.');
            if (temp.Length > 0 && temp[temp.Length - 1].ToLower() == "aspx")
            {
                application.Response.Filter = new AnalyticsStream(application.Response.Filter);
            }
        } 

        class AnalyticsStream : Stream
        {
            Stream innerStream;          
            MemoryStream memory = new MemoryStream(); 

            public AnalyticsStream(Stream innerStream)
            {
                this.innerStream = innerStream;            
            } 

            public override void Close()
            {
                memory.Position = 0;
                using (StreamWriter writer = new StreamWriter(innerStream))
                {
                    using (StreamReader reader = new StreamReader(memory))
                    {
                        while (!reader.EndOfStream)
                        {
                            // Find </body>
                            if (MatchesOrWrite(reader, writer, '<', null) &&
                                MatchesOrWrite(reader, writer, '/', "<") &&
                                MatchesOrWrite(reader, writer, 'b', "</") &&
                                MatchesOrWrite(reader, writer, 'o', "</b") &&
                                MatchesOrWrite(reader, writer, 'd', "</bo") &&
                                MatchesOrWrite(reader, writer, 'y', "</bod") &&
                                MatchesOrWrite(reader, writer, '>', "</body"))
                            {
                                //string script = String.Format(GoogleScript, accountNumber) + "</body>";
                                writer.Write(GoogleScript);
                                while (!reader.EndOfStream)
                                    writer.Write((char)reader.Read());
                            }
                        }
                    }
                } 

                base.Close();
            } 

            private bool MatchesOrWrite(StreamReader reader, StreamWriter writer, char target, string buffered)
            {
                if (!reader.EndOfStream)
                {
                    char current = (char)reader.Read();
                    if (current == target)
                    {
                        return true;
                    }
                    else
                    {
                        writer.Write(buffered);
                        writer.Write(current);
                    }
                }
                else
                {
                    writer.Write(buffered);
                } 

                return false;
            } 

            public override bool CanRead
            {
                get { return memory.CanRead; }
            } 

            public override bool CanSeek
            {
                get { return memory.CanSeek; }
            } 

            public override bool CanWrite
            {
                get { return memory.CanWrite; }
            } 

            public override void Flush()
            {
                memory.Flush();
            } 

            public override long Length
            {
                get { return memory.Length; }
            } 

            public override long Position
            {
                get
                {
                    return memory.Position;
                }
                set
                {
                    memory.Position = value;
                }
            } 

            public override int Read(byte[] buffer, int offset, int count)
            {
                return memory.Read(buffer, offset, count);
            } 

            public override long Seek(long offset, SeekOrigin origin)
            {
                throw new NotImplementedException();
            } 

            public override void SetLength(long value)
            {
                memory.SetLength(value);
            } 

            public override void Write(byte[] buffer, int offset, int count)
            {
                memory.Write(buffer, offset, count);
            }
        }
    }
} 

2.
编译得到PiwikAnalytics.dll,注册到GAC中【需要强命名的哦~】,不然要每个子站点都拷贝一份。
如何在visual studio中强命名程序集:(推荐)  http://www.cnblogs.com/awpatp/archive/2010/02/07/1665530.html
文章中也提到了如果获取程序集的PublicKeyToken,其实不用那么麻烦,把程序集放到GAC中,有一列会显示PublicKeyToken的~。
•    GAC注册:http://www.cnblogs.com/mljmalongjiang/archive/2008/07/31/1257135.html
•    另外有种更简便的方式,直接把dll托到 c:\windows\assembly文件夹中【推荐】
另外一种方式强命名程序集:http://www.cnblogs.com/zhongge/articles/1207183.html
经过上述步骤,我们已经把PiwikAnalytics.dll注册到GAC了,那我们在web.config中做一下配置就要大功告成了!
3. web.config默认路径C:\inetpub\wwwroot,如果没有web.config可直接新建的~

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="PiwikAnalyticsSites" value="site,4;meeting,6"/>    
  </appSettings>
  <system.web>    
    <authentication mode="Windows"/>
    <httpModules>
      <add name="PiwikAnalytics" type="PiwikAnalytics.PiwikAnalyticsModule"/>
    </httpModules>
    <compilation debug="true">
      <assemblies>
        <add assembly="PiwikAnalytics, version=1.0.0.0, Culture=neutral,PublicKeyToken=0c64deee0d840dfb" />
      </assemblies>
    </compilation>
  </system.web>
</configuration> 

要记得把从步骤2中得到的PublicKeyToken替换成你自己的哦~
到此时,重启iis,刷新页面。再去piwik中查看,大功告成!
需特别注意的地方:
1.    注册module时,要按照自己的实际情况配置
2.    上述方式不适用于MVC和模板模式开发
3.    每次改写代码的时候都需要重新生成一次DLL,并且重新注册GAC,并且对站点相应应用程序池中的进行回收
More:另外介绍2个pwiki客户端查看软件
•    Desktop Web Analytics
•    Piwik Connector
Over 收工!

posted @ 2010-05-07 00:05 广思 阅读(178) 评论(0) 编辑

2009年11月30日

注册表中启用对没有标记为安全的 ActiveX 控件进行初始化和脚本运行

启用

对没有标记为安全的 ActiveX 控件进行初始化和脚本运行

找到注册表项

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\0

修改 1201  项值为0

 

微软参考:

Internet Explorer 安全区域注册表项说明

posted @ 2009-11-30 17:35 广思 阅读(456) 评论(0) 编辑

2009年11月27日

安装Qvode后,在IE8的菜单工具中会出现《彩票》

删除这个《彩票》,看的不爽!
找到指定注册表节,删除
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Extensions\{82D9671E-0B56-4285-92CD-15BC08B883BB}
关闭IE,然后再打开就好了

posted @ 2009-11-27 17:11 广思 阅读(122) 评论(0) 编辑

2009年11月11日

将字符串写入图片

将字符串写入到图片中.

1 换行采用指定写入位置来实现

2 务必释放资源,否则会出现Win32Error 

 

 protected void Page_Load(object sender, EventArgs e)
        {
            
if (!IsPostBack)
            {
                
//前一页面传递过来的参数
                string email = Request.QueryString.Get("email");
                
string realName = new OLUserService.OLUserService().GetRealNameByEmail(email);
                
string workid = new OLUserService.OLUserService().GetWorkIdByEmail(email);

                
//image1图片控件-呈现写入字符串后的图片
                string fileName = this.image1.ImageUrl;
                
int index = fileName.LastIndexOf(".");

                
string newFileName = fileName.Substring(0, index) + "_" + realName + fileName.Substring(index);
                FileInfo fileInfo 
= new FileInfo(Server.MapPath(fileName));
                fileInfo.CopyTo(Server.MapPath(newFileName), 
true);

                System.Drawing.Image image 
= new Bitmap(Server.MapPath(newFileName));
                Graphics g 
= Graphics.FromImage(image);
                
                
string s2 = string.Format("通过了关于《集团商业行为准则》的{0}", DateTime.Now.ToString("yyyy"));
                
string s3 = "年度认证,特此证明。";

                Font drawFont 
= new Font("Arial"12);
                SolidBrush drawBrush 
= new SolidBrush(Color.Black);
                
                
//通过指定写入位置实现换行功能
                drawPoint = new PointF(50200);
                g.DrawString(s2, drawFont, drawBrush, drawPoint);

                drawPoint 
= new PointF(50230);
                g.DrawString(s3, drawFont, drawBrush, drawPoint);
               

                System.Drawing.Image img 
= new Bitmap(image);
                
//此处尤为重要,使用资源后的释放.否则会出现Win32错误

                
//[ExternalException (0x80004005): A generic error occurred in GDI+.]

                g.Dispose();
                image.Dispose();

                img.Save(Server.MapPath(newFileName), System.Drawing.Imaging.ImageFormat.Jpeg);
                
this.image1.ImageUrl = newFileName;
            }
        }

 

 

 

 

 

posted @ 2009-11-11 11:22 广思 阅读(207) 评论(1) 编辑

2009年10月19日

TRUNCATE 删除表内所有记录

今天删除一个数据库中的记录,数据有400万条,删的都怕了,忽然间想起来有个删除语句。终于找到了,可还是无法满足我的要求,TRUNCATE 是清空所有记录。抄下来备查了~

TRUNCATE TABLE

删除表中的所有行,而不记录单个行删除操作。

语法

TRUNCATE TABLE name

参数

name

是要截断的表的名称或要删除其全部行的表的名称。

注释

TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。

DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。

TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。

对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。

TRUNCATE TABLE 不能用于参与了索引视图的表。

示例

下例删除 authors 表中的所有数据。

TRUNCATE TABLE authors
权限

TRUNCATE TABLE 权限默认授予表所有者、sysadmin 固定服务器角色成员、db_ownerdb_ddladmin 固定数据库角色成员且不可转让

posted @ 2009-10-19 18:36 广思 阅读(185) 评论(0) 编辑

2009年9月25日

Windows Server 2003 SP1本机访问报错-环回检查

摘要: 搭建好的程序本机无法正常访问,返回HTTP401.1错误。客户端却能正常访问如果安装 Microsoft Windows Server 2003 Service Pack 1 (SP1),则会出现此问题。Windows Server 2003 SP1 包括一个环回检查安全功能,用于帮助防止计算机受到反射攻击。因此,如果所使用的 FQDN 或自定义的主机标头与本地计算机名称不匹配,则会出现身份验证失...阅读全文

posted @ 2009-09-25 10:23 广思 阅读(168) 评论(0) 编辑

2009年6月26日

通过Object传递参数

摘要: Tip: How to pass initialize parameters to Silverlight application using <object> element? If you want to pass initialize parameters to Silverlight application from an HTML/ASPX page, you have to...阅读全文

posted @ 2009-06-26 10:01 广思 阅读(79) 评论(0) 编辑

2009年5月14日

SQL Server 镜像部署

摘要: 数据库镜像配置参考资料:http://tech.it168.com/db/s/2007-04-24/200704240837593_1.shtml用SQL命令方式配置数据库镜像.http://msdn.microsoft.com/zh-cn/library/ms189852.aspx数据库镜像概述实施步骤:本文档主要讲解如何用SQLServer管理台配置数据库镜像主服务器: tb-develop镜...阅读全文

posted @ 2009-05-14 15:02 广思 阅读(285) 评论(1) 编辑

使用stsadm.exe工具实现SharePoint网站备份还原

摘要: 使用stsadm.exe工具实现SharePoint网站备份还原一、过程概要:首先在源站点机器上用stsadm.exe备份网站集,讲备份文件拷贝到目标服务器(也可直接在备份时配置备份路径为目标机器路径),然后执行还原操作:首先新建网站集,然后用SharePoint自带的stsadm.exe工具来实现站点的还原.还原完成后拷贝sp.listview控件所需dll并且修改web.Config配置文件。...阅读全文

posted @ 2009-05-14 14:51 广思 阅读(861) 评论(0) 编辑

2009年4月29日

不能打开文件:mk:@MSITStore:路径[cannot open the file mk@MSITstore:路径]解决办法 转

摘要: 转自:http://hi.baidu.com/vking/blog/item/5bbce4dd2d5b7aec76c638bc.html/cmtid/7897a9d33626523e970a16a9不能打开文件:mk:@MSITStore:路径[cannot open the file mk@MSITstore:路径]2007年12月11日 星期二 上午 11:50不能打开文件:mk:@MSITS...阅读全文

posted @ 2009-04-29 13:32 广思 阅读(777) 评论(0) 编辑