我跟踪软件的下载和使用情况的方法
2008-12-24 17:26
471 查看
做为一个共享软件开发者,软件发布出去以后,我们很关心用户使用软件的情况--到底有多少人在用我的软件?是否常用?什么时候下载的?什么时候开始用的?用了多久了?用户忠诚度如何?
这些数据如何获得呢?从软件下载站或者自己的网站,我们只能获得软件的下载次数以及网站的访问统计数据。更详细的数据需要我们的软件提供。
很多数据我们自己的软件当然能够获得,只是,软件什么时候向我们提交这些数据呢?很自然的,我想到了软件自动更新。我的软件提供自动更新功能,软件会定期访问我的服务器检测是否存在新版本的程序,于是可以在检测新版程序的同时,向服务器提交软件的一些我们所关心数据(当然,不能包含用户的隐私数据),这些数据可以包括:用户软件的当前版本,用户使用软件的次数以及软件的安装时间,用户唯一ID(为了跟踪某个用户的长期的使用情况,而为每个用户分配一个唯一的ID号)。
上面这些数据的获取是没有什么问题。但是我还想知道用户是从哪里下载的软件?用户从官方下载软件时,是从哪个网站连入软件官网的?用户下载软件的时候是什么时候?这些数据的获取就比较麻烦了--要实现这个功能,需要实现,每次下载软件时,下载的文件内容会不同(下载的文件要包含用户的下载时间,入站地址等信息)。我的想法是,使用php(或别的动态网页技术)来处理软件安装程序的下载请求,然后通过php(或别的动态网页技术)控制软件安装程序的下载内容,在文件最后,附加上下载时间,入站地址等信息。下面是我现实此功能的php程序的伪代码:
clearstatcache();
if (!file_exists($file))
{
//文件不存在
die("file not existed!");
}
$len = filesize($file);
$filename = basename($file);
$ctype = "application/octet-stream";
$externInfo = "";
//额外信息起始位置标识
$externInfoFlag = '****ExternInfo****-=Flystarsoft=-{F3A1A1AE-80CA-4bd8-B5E3-457E7DE9AB77}&1j_123ajJ*jdfaa83a:' . "/r/n";
$downloadTime = time();
$remote_addr = "0.0.0.0";
if (isset($_SERVER["REMOTE_ADDR"]))
{
$remote_addr = $_SERVER["REMOTE_ADDR"];
}
$downloadId = md5("md5" . $this->m_downloadSite . $downloadTime . $remote_addr . rand() . rand());//生成唯一下载ID
$externInfo = $externInfoFlag.
"DownloadSite=" . $this->m_downloadSite . "/r/n" .
"DownloadId=" . $downloadId . "/r/n" .
"DownloadTime=" . $downloadTime . "/r/n/r/n/r/n";
//说明:这面的DownloadSite是指软件的入站地址,用户从Google搜索到我的软件后,通过Google进入我们
// 软件并下载了我的软件,这时所要附加的额外信息中DownloadSite将为“www.Google.com”。
//在额外信息后面增加空白符,使得整个额外信息的长度为512字节
$addSpaces = 512 - strlen($externInfo);
for ($i = 0; $i < $addSpaces; $i++)
{
$externInfo = $externInfo . " ";
}
$len = $len + strlen($externInfo);
@ob_end_clean();
@set_time_limit(0);
//输出文件下载的HTTP头
header("Cache-Control: public, must-revalidate");
header('Cache-Control: pre-check=0, post-check=0, max-age=0');
header("Pragma: no-cache");
header("Expires: 0");
header("Content-Description: File Transfer");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Content-Type: " . $ctype);
header("Content-Length: ".(string)$len);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary/n");
//发送文件内容
@readfile($file);
//发送附加额外信息
@print($externInfo);
这样,所有从官网上下载的软件安装程序,都会在其后而增加我们所需要的附加信息。那么,我们如何获取到这些信息的?要取得这些信息,只能在安装程序运行时获取,大家都知道InnoSetup可以提供DLL按扩展其功能,而我的软件本来就是用InnoSetup来制作安装程序的,所以我自然的就想到了,利用InnoSetup调用DLL,读取当前运行的安装程序文件的最后一段数据,并通过额外信息起位位置标识来读取下载安装程序时在其最后增加的额外信息,然后再将这些信息保存下后,以后每个进行软件更新检测时,就可以附加这些信息。大家还可以交流一下,看还能提供哪些有用信息。有了这些信息后,就可以更好的得到软件用户使用这款软件的情况了。
下面是由InnoSetup调用的,读取保存在安装程序中额外信息的C++伪代码:
//取当前进程的父进程
//注:对InnoSetup而言,装载DLL的父进程的程序才是原来的安装程序(Setup.exe),
// 当前进程是从安装程序中解压出来的一个安装过程控制程序
DWORD parentProcessId = GetParentProcessId(GetCurrentProcessId);
//取当前程序的父进程(即安装程序)的可执行程序文件名
CCharString setupExecFilename = GetProcessModuleFilename(parentProcessId);
FILE *fp = fopen(setupExecFilename, "rb");
if (fp == NULL)
{
return FALSE;
}
//提取文件的最后512字节
const int LAST_BYTES = 512
if (fseek(fp, -LAST_BYTES, SEEK_END) != 0)
{
//提取失败
fclose (fp);
return FALSE;
}
CMyString lastInformats;
if (fread(lastInformats.GetBufferAsLength(LAST_BYTES), 1, LAST_BYTES, fp)
!= LAST_BYTES)
{
//提取失败
fclose(fp);
return FALSE;
}
lastInformats.ReleaseBuffer(LAST_BYTES);
fclose(fp);
fp = NULL;
//确定额外信息的位置
int infoPos = lastInformats.Find(LOCATE_FLAG);
if (infoPos <= 0)
{
//无额外信息(认为获取到空的额外信息)
return TRUE;
}
//分离额外信息
CMyString externInfo = lastInformats.Mid(infoPos + strlen(LOCATE_FLAG));
downloadSite = ReadExternInfo(externInfo, "DownloadSite", "");
downloadId = ReadExternInfo(externInfo, "DownloadId", "");
downloadTime = TimetToString((time_t)strtoul(GetResultValue(externInfo, "DownloadTime", "0"), NULL, 10));
//写入注册表
WriteToRegistry("downloadSite", downloadSite);
WriteToRegistry("downloadId", downloadId);
WriteToRegistry("downloadTime", downloadTime);
目前,我已经在我的软件中使用上述方法跟踪软件的下载和使用请求,目前感觉效果还比较理想。当然,这里面还有一个问题,就是有些下载站会从我的软件官方上下载程序,然后放到他们的网站上给用户下载,这样,所有这些用户的下载时间、下载站点都将完全相同,不过好在有一个唯一下载ID,根据这个标识可以很容易的分辨这些用户,在进行数据统计时,直接忽略掉这些数据即可。
目前,我使用这个方法时间也不长,等过段时间再和大家交流一下这种方法的使用效果吧。 :D
这些数据如何获得呢?从软件下载站或者自己的网站,我们只能获得软件的下载次数以及网站的访问统计数据。更详细的数据需要我们的软件提供。
很多数据我们自己的软件当然能够获得,只是,软件什么时候向我们提交这些数据呢?很自然的,我想到了软件自动更新。我的软件提供自动更新功能,软件会定期访问我的服务器检测是否存在新版本的程序,于是可以在检测新版程序的同时,向服务器提交软件的一些我们所关心数据(当然,不能包含用户的隐私数据),这些数据可以包括:用户软件的当前版本,用户使用软件的次数以及软件的安装时间,用户唯一ID(为了跟踪某个用户的长期的使用情况,而为每个用户分配一个唯一的ID号)。
上面这些数据的获取是没有什么问题。但是我还想知道用户是从哪里下载的软件?用户从官方下载软件时,是从哪个网站连入软件官网的?用户下载软件的时候是什么时候?这些数据的获取就比较麻烦了--要实现这个功能,需要实现,每次下载软件时,下载的文件内容会不同(下载的文件要包含用户的下载时间,入站地址等信息)。我的想法是,使用php(或别的动态网页技术)来处理软件安装程序的下载请求,然后通过php(或别的动态网页技术)控制软件安装程序的下载内容,在文件最后,附加上下载时间,入站地址等信息。下面是我现实此功能的php程序的伪代码:
clearstatcache();
if (!file_exists($file))
{
//文件不存在
die("file not existed!");
}
$len = filesize($file);
$filename = basename($file);
$ctype = "application/octet-stream";
$externInfo = "";
//额外信息起始位置标识
$externInfoFlag = '****ExternInfo****-=Flystarsoft=-{F3A1A1AE-80CA-4bd8-B5E3-457E7DE9AB77}&1j_123ajJ*jdfaa83a:' . "/r/n";
$downloadTime = time();
$remote_addr = "0.0.0.0";
if (isset($_SERVER["REMOTE_ADDR"]))
{
$remote_addr = $_SERVER["REMOTE_ADDR"];
}
$downloadId = md5("md5" . $this->m_downloadSite . $downloadTime . $remote_addr . rand() . rand());//生成唯一下载ID
$externInfo = $externInfoFlag.
"DownloadSite=" . $this->m_downloadSite . "/r/n" .
"DownloadId=" . $downloadId . "/r/n" .
"DownloadTime=" . $downloadTime . "/r/n/r/n/r/n";
//说明:这面的DownloadSite是指软件的入站地址,用户从Google搜索到我的软件后,通过Google进入我们
// 软件并下载了我的软件,这时所要附加的额外信息中DownloadSite将为“www.Google.com”。
//在额外信息后面增加空白符,使得整个额外信息的长度为512字节
$addSpaces = 512 - strlen($externInfo);
for ($i = 0; $i < $addSpaces; $i++)
{
$externInfo = $externInfo . " ";
}
$len = $len + strlen($externInfo);
@ob_end_clean();
@set_time_limit(0);
//输出文件下载的HTTP头
header("Cache-Control: public, must-revalidate");
header('Cache-Control: pre-check=0, post-check=0, max-age=0');
header("Pragma: no-cache");
header("Expires: 0");
header("Content-Description: File Transfer");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
header("Content-Type: " . $ctype);
header("Content-Length: ".(string)$len);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary/n");
//发送文件内容
@readfile($file);
//发送附加额外信息
@print($externInfo);
这样,所有从官网上下载的软件安装程序,都会在其后而增加我们所需要的附加信息。那么,我们如何获取到这些信息的?要取得这些信息,只能在安装程序运行时获取,大家都知道InnoSetup可以提供DLL按扩展其功能,而我的软件本来就是用InnoSetup来制作安装程序的,所以我自然的就想到了,利用InnoSetup调用DLL,读取当前运行的安装程序文件的最后一段数据,并通过额外信息起位位置标识来读取下载安装程序时在其最后增加的额外信息,然后再将这些信息保存下后,以后每个进行软件更新检测时,就可以附加这些信息。大家还可以交流一下,看还能提供哪些有用信息。有了这些信息后,就可以更好的得到软件用户使用这款软件的情况了。
下面是由InnoSetup调用的,读取保存在安装程序中额外信息的C++伪代码:
//取当前进程的父进程
//注:对InnoSetup而言,装载DLL的父进程的程序才是原来的安装程序(Setup.exe),
// 当前进程是从安装程序中解压出来的一个安装过程控制程序
DWORD parentProcessId = GetParentProcessId(GetCurrentProcessId);
//取当前程序的父进程(即安装程序)的可执行程序文件名
CCharString setupExecFilename = GetProcessModuleFilename(parentProcessId);
FILE *fp = fopen(setupExecFilename, "rb");
if (fp == NULL)
{
return FALSE;
}
//提取文件的最后512字节
const int LAST_BYTES = 512
if (fseek(fp, -LAST_BYTES, SEEK_END) != 0)
{
//提取失败
fclose (fp);
return FALSE;
}
CMyString lastInformats;
if (fread(lastInformats.GetBufferAsLength(LAST_BYTES), 1, LAST_BYTES, fp)
!= LAST_BYTES)
{
//提取失败
fclose(fp);
return FALSE;
}
lastInformats.ReleaseBuffer(LAST_BYTES);
fclose(fp);
fp = NULL;
//确定额外信息的位置
int infoPos = lastInformats.Find(LOCATE_FLAG);
if (infoPos <= 0)
{
//无额外信息(认为获取到空的额外信息)
return TRUE;
}
//分离额外信息
CMyString externInfo = lastInformats.Mid(infoPos + strlen(LOCATE_FLAG));
downloadSite = ReadExternInfo(externInfo, "DownloadSite", "");
downloadId = ReadExternInfo(externInfo, "DownloadId", "");
downloadTime = TimetToString((time_t)strtoul(GetResultValue(externInfo, "DownloadTime", "0"), NULL, 10));
//写入注册表
WriteToRegistry("downloadSite", downloadSite);
WriteToRegistry("downloadId", downloadId);
WriteToRegistry("downloadTime", downloadTime);
目前,我已经在我的软件中使用上述方法跟踪软件的下载和使用请求,目前感觉效果还比较理想。当然,这里面还有一个问题,就是有些下载站会从我的软件官方上下载程序,然后放到他们的网站上给用户下载,这样,所有这些用户的下载时间、下载站点都将完全相同,不过好在有一个唯一下载ID,根据这个标识可以很容易的分辨这些用户,在进行数据统计时,直接忽略掉这些数据即可。
目前,我使用这个方法时间也不长,等过段时间再和大家交流一下这种方法的使用效果吧。 :D
相关文章推荐
- 使用Mac App Store更新、下载软件时出现未知错误的解决方法
- win2008中限制使用迅雷下载的方法[软件策略]
- 使用远程管理软件VNC死机情况解决方法
- 启明星win7桌面天气预报软件下载与使用方法(带时间)
- [置顶] 骂人软件绿色中文版下载(附使用方法)
- FastQC 质控软件的下载及使用方法(一)
- Dependency Walker使用说明(对比软件运行与跟踪情况)
- 【资源分享】GIF屏幕录制软件&&GIF轻量级编辑软件(含动图使用方法和下载链接)
- 关于传统的软件开发方法在实际软件开发过程中的使用情况
- 使用ADB上传、下载文件和安装软件的方法
- Nero9中文破解版小李探花刻录软件免费下载(附序列号+下载地址+使用方法)
- PHP源代码加密软件工具Zend Guard™下载及使用方法
- matlab7.0安装 win7系统详细使用方法附软件下载
- 开发环境操作系统镜像文件与软件说明-win7-64bit--请下载后使用u盘镜像安装
- 论坛自动顶贴机下载和使用方法(qq:525093551 发布)
- matlab工具箱下载安装和使用方法的汇总|Toolbox 大全
- Linux下查看内存使用情况方法总结
- jacob下载问题, Office word 此文件正由另一应用程序或用户使用的解决方法
- PHP 使用header函数设置HTTP头的示例方法 表头 (xlsx下载)
- 嵌入式系统内存使用情况评估方法探究