摘 要 介绍了Windows磁盘清理工具二次开发的扩展接口 对其接口加以分解 并运用ATL库具体实现了清理 tmp 临时文件的功能
关键词 磁盘清理工具 ATL库 接口
引言
Windows磁盘清理工具(Disk CleanUp)是一个实用快捷并拥有简单易用界面的系统清理软件 更值得系统开发管理人员注意的是 此系统清理软件是建立在以技术为基础发展的 支持第三方插件 并且可以根据需要自制定义功能二次开发的平台 在这里 我们对于Windows磁盘清理工具的开发接口做深入地研究 在此基础上举例示范添加一个查找 tmp 临时文件的功能
技术讨论
微软的技术广泛地运用在Windows的模块化设计中 致使支持二次开发 关于技术基础与应用 可参考 在此 我们只为Windows磁盘清理工具 简称清理工具的扩展接口加以分解 清理工具首次出现在Windows *** 作系统中 并在后来推出的Windows版本中予以改进 添加了新的功能 比如说 在NTFS的文件系统下 自动压缩不经常访问的文件 这些新功能通过模块实现 在清理工具中作为插件调用 早期的版本是通过IEmptyVolumeCache接口调用 在Windows 以后的版本中 还加入了IEmptyVolumeCache 接口 加入了较小的更新
IEmptyVolumeCache接口由五个函数组成 根据呼叫的顺序 分别是
virtual / [local] / HRESULT STDMETHODCALLTYPE initialize ( / [in] / HKEY RegKey / [in] / LPCWSTR pcwszVolume / [out] / LPWSTR ppwszDisplayName / [out] / LPWSTR ppwszDescription / [out] / DWORD pdwFlags) = ;virtual HRESULT STDMETHODCALLTYPE getspaceused ( / [out] / DWORDLONG pdwlSpaceUsed / [in] / IEmptyVolumeCacheCallBack picb) = ;virtual HRESULT STDMETHODCALLTYPE showproperties ( / [in] / HWND hwnd) = ;virtual HRESULT STDMETHODCALLTYPE purge ( / [in] / DWORDLONG dwlSpaceToFree / [in] / IEmptyVolumeCacheCallBack picb) = ;virtual HRESULT STDMETHODCALLTYPE deactivate ( / [out] / DWORD pdwFlags) = ;
清理工具在正常执行时 首先调用Initialize初始化插件 随后执行GetSpaceUsed来扫描可清除的文件大小 扫描完毕后 清理工具的主界面就出现了如图 所示 在此 我们加入了清理TMP文件的功能可以浏览不同的清理文件种类 列表中的每一个文件种类均由一个插件实现 除了阅览可清理文件大小以外 用户在可以点击一个可自定义的按钮 调用插件的ShowProperties功能 以显示更详细的资料 如用户选择OK 清理工具就调用Purge函数 清理扫描出来的文件 最后 Deactivate函数被调用 终止插件的应用
运用于Windows 以后的清理工具的插件也应该支持IEmptyVolumeCache的接口 IEmptyVolumeCache只由一个函数组成
virtual / [local] / HRESULT STDMETHODCALLTYPE initializeex ( / [in] / HKEY RegKey / [in] / LPCWSTR pcwszVolume / [in] / LPCWSTR pcwszKeyName / [out] / LPWSTR ppwszDisplayName / [out] / LPWSTR ppwszDescription / [out] / LPWSTR ppwszBtnText / [out] / DWORD pdwFlags) = ;
InitializeEx增加了更严格的本地化语言要求 加强了国际化的支持 并且允许自定义按钮的显示文字 pdwFlags变量用于在工具与插件间传递信息 支持下列旗标
EVCF_OUTOFDISKSPACE EVCF_SETTINGSMODE EVCF_DONTSHOWIFZERO EVCF_ENABLEBYDEFAULT EVCF_ENABLEBYDEFAULT_AUTO EVCF_HASSETTINGS EVCF_REMOVEFROMLIST
EVCF_OUTOFDISKSPACE与EVCF_SETTINGSMODE用于工具传递给插件的设定 EVCF_OUTOFDISKSPACE表示当前硬盘的空余空间非常有限 需要尽可能多地清理 即使是系统的性能会受到影响 EVCF_SETTINGSMODE表示可定期执行的无人控制模式 在此模式下 GetSpaceUsed Purge 及ShowProperties都将不予调用 所有清理任务应予InitializeEx时执行 其它旗标用于插件传递给工具的不同运行模式 EVCF_DONTSHOWIFZERO表示在没有找到可删除文件时不显示此类型 EVCF_ENABLEBYDEFAULT表示此类型文件可以安全删除 EVCF_ENABLEBYDEFAULT_AUTO表示此类型文件可以非常安全的删除 EVCF_HASSETTINGS表示此插件支持ShowProperties功能 可以显示详细信息 EVCF_REMOVEFROMLIST表示是一次性清理任务 清理工具在执行后自动将插件关闭 以后不再执行
图 清理工具的主界面
实现方法
我们开发一个新的清理工具插件 扫描并清理 TMP文件 的编程有多种方法 我们选择了ATL库 关于ATL库的运用
我们在Visual Studio Net 中生成新的ATL的DLL Server项目 并使用Add Class加入新的ATL Simple Object控件类CCleanSimpleHandler 在定义中 我们让CCleanSimpleHandler从IEmptyVolumeCache 继承 并且 我们添加了下列变量
// 储存扫描出文件的大小DWORDLONG m_dwlFileSize; // 储存根目录WCHAR m_strRootDir[MAX_PATH];// 储存扫描出文件列表std::vector<WCHAR > m_lstFilesToDel;
然后 我们一一实现IEmptyVolumeCache及IEmptyVolumeCache 接口的函数 在下面的代码列表中 没有包括严格的检查错误返回值 这是为了简短代码的长度 提高可读性 在实际应用中 检查错误返回值是不可少的 为了不同版本Windows兼容 我们在InitializeEx中调用Initialize
HRESULT CCleanSimpleHandler::InitializeEx (HKEY hKey LPCWSTR pcwszVolume LPCWSTR pcwszKeyName LPWSTR ppwszDisplayName LPWSTR ppwszDescription LPWSTR ppwszBtnText DWORD pdwFlags) { HRESULT hr = Initialize (hKey pcwszVolume ppwszDisplayName ppwszDescription pdwFlags); ppwszBtnText = (LPWSTR) CoTaskMemAlloc ( sizeof (WCHAR)); StrCpyW(ppwszBtnText L View files );return hr;}HRESULT CCleanSimpleHandler::Initialize (HKEY hKey LPCWSTR pcwszVolume LPWSTR ppwszDisplayName LPWSTR ppwszDescription DWORD pdwFlags){ StrCpyW(m_strRootDir pcwszVolume); ppwszDisplayName = (LPWSTR) CoTaskMemAlloc( sizeof (WCHAR)); StrCpyW(ppwszDisplayName L TMP files ); ppwszDescription = (LPWSTR) CoTaskMemAlloc ( sizeof (WCHAR)); StrCpyW(ppwszDescription L Temporary files TMP ); pdwFlags = EVCF_HASSETTINGS | EVCF_ENABLEBYDEFAULT; m_dwlFileSize = ; return S_OK;}
在GetSpaceUsed中 我们调用ScanDir来扫描 TMP文件 储存在m_lstFilesToDel中 GetSpaceUsed的第二个参数是IEmptyVolumeCacheCallBack接口的指针 用于调用其ScanProgress函数以报告扫描的进展情况 ScanProgress函数定义是
HRESULT ScanProgress(DWORDLONG dwlSpaceUsed DWORD dwFlags LPCWSTR pwszReserved)
其中dwFlags正常应设为零 在结束时改为EVCCBF_LASTNOTIFICATION ScanProgress函数的返回值很重要 因为用户可以在任何时候中断在进行中的清理任务 如ScanProgress返回E_ABORT GetSpaceUsed应最快终端扫描 函数返回 因此 我们在递归的目录扫描函数ScanDir中 加入了如中断立即退出的功能
HRESULT CCleanSimpleHandler::GetSpaceUsed (DWORDLONG pdwSpaceUsed IEmptyVolumeCacheCallBack picb){m_dwlFileSize = ; ScanDir(m_strRootDir picb); picb >ScanProgress(m_dwlFileSize EVCCBF_LASTNOTIFICATION NULL); pdwSpaceUsed = m_dwlFileSize; return S_OK;}bool CCleanSimpleHandler::ScanDir(WCHAR szDir IEmptyVolumeCacheCallBack pcib){ WCHAR strPath[MAX_PATH]; WCHAR pchPathFileName; bool cancelled = false; WIN _FIND_DATAW fd; HANDLE hFind; if (cancelled = FAILED(pcib >ScanProgress(m_dwlFileSize NULL NULL))) return false; StrCpyW(strPath szDir); PathAppendW(strPath L ); pchPathFileName = strPath+lstrlenW(strPath) ; hFind = FindFirstFileW(strPath &fd); if (hFind == INVALID_HANDLE_VALUE) // E g Due to security issuesreturn true;do { StrCpyW(pchPathFileName fd cFileName); if ((fd dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {if (fd cFileName[ ] != ) { if (cancelled = !ScanDir(strPath pcib)) break;} } else { WCHAR pchExt = PathFindExtensionW(strPath);if ( StrCmpIW(pchExt L tmp ) == ) { m_dwlFileSize += ((DWORDLONG)fd nFileSizeHigh) + fd nFileSizeLow; WCHAR filename = (WCHAR )CoTaskMemAlloc((lstrlenW(strPath)+ ) sizeof(WCHAR)); StrCpyW(filename strPath); m_lstFilesToDel push_back(filename);} }} while (FindNextFileW(hFind &fd) != NULL);FindClose(hFind);return !cancelled;}
其他的函数很简单 Purge函数将扫描出的文件列表m_lstFilesToDel中的文件一一删除 ShowProperties中 我们显示扫描出来的文件 最后 Deactivate将分配的内存释放
HRESULT CCleanSimpleHandler::Purge (DWORDLONG dwSpaceToFree IEmptyVolumeCacheCallBack picb){ for (unsigned int i= ; i < m_lstFilesToDel size(); ++i)DeleteFileW(m_lstFilesToDel[i]);return S_OK;}HRESULT CCleanSimpleHandler::ShowProperties (HWND hWnd){ for (unsigned int i= ; i < m_lstFilesToDel size(); ++i)if (MessageBoxW(hWnd m_lstFilesToDel[i] L View filesMB_OKCANCEL|MB_ICONINFORMATION)==IDCANCEL) break; return S_OK;}HRESULT CCleanSimpleHandler::Deactivate (LPDWORD pdwFlags){ for (unsigned int i= ; i < m_lstFilesToDel size(); ++i)CoTaskMemFree(m_lstFilesToDel[i]);m_lstFilesToDel clear();pdwFlags = ;return S_OK;
结论和建议
lishixinzhi/Article/program/net/201311/13334复制下面的所有东西,粘贴到一个txt文件里,然后将扩展名改为sma,然后利用cs插件里的scripting文件里的compileexe将文件改成amxx然后安装一个amxx就能用了,你要复制的是:
/ AMX Mod script
(c) Copyright 2002, OLO
This file is provided as is (no warranties)
/
/ cmds:
amx_cc_check < cvar | alias >
checks if cvar or alias exists
(fe: amx_cc_check xxxaimbot)
amx_fc_cfg < cfg >
forces configuration
(fe: amx_fc_cfg cl_forwardspeed 400)
You may keep configuration in servercfg
or in addons/amx/cfgchkcfg
/
#include <amxmod>
#define MAX_FORCES 192
#define MAX_CHECKS 24
#define CHECK_NEXT 763734
#define FORCE_NEXT 235334
#define CHECK_TIMEOUT 154675
#define FORCE_TIMEOUT 843522
new CHECK_CLOSE[8] = {"amxcc"}
new FORCE_CLOSE[8] = {"amxcf"}
new cfg_check[MAX_CHECKS][32]
new cfg_num = 0
new cfg_force[MAX_FORCES][32]
new cfg_vforce[MAX_FORCES][32]
new cfg_force_num = 0
new success_cc[33]
new success_cf[33]
new close_code_cc[33][6]
new close_code_cf[33][6]
new position_cc[33]
new position_cf[33]
do_checking(id,pos){
new param[3]
param[0] = id
position_cc[id] = pos
set_task(05,"fchecking",CHECK_NEXT+id,param,2)
}
do_forcing(id,pos){
new param[3]
param[0] = id
position_cf[id] = pos
set_task(03,"fforcing",FORCE_NEXT+id,param,2)
}
public fchecking(param[]){
new id = param[0]
success_cc[id] = 0
format(close_code_cc[id],4,"%c%c%c",random_num('a','z'),random_num('a','z'),random_num('a','z'))
client_cmd(id,"%s;%s %s",cfg_check[position_cc[id]],CHECK_CLOSE,close_code_cc[id])
set_task(100,"time_out",CHECK_TIMEOUT+id,param,2)
}
public fforcing(param[]){
new id = param[0]
new posid = position_cf[id]
success_cf[id] = 0
format(close_code_cf[id],4,"%c%c%c",random_num('a','z'),random_num('a','z'),random_num('a','z'))
client_cmd(id,"%s %s;%s %s",cfg_force[posid],cfg_vforce[posid],FORCE_CLOSE,close_code_cf[id])
client_cmd(id,"alias %s ^"echo [AMX] %s is %s^"",cfg_force[posid],cfg_force[posid],cfg_vforce[posid])
set_task(100,"time_out",FORCE_TIMEOUT+id,param,2)
}
public client_command(id){
if (!success_cc[id]){
new arg[16]
read_argv(0,arg,15)
if (equal(arg,cfg_check[position_cc[id]])){
success_cc[id] = 1
remove_task(CHECK_TIMEOUT+id)
return PLUGIN_HANDLED
}
}
else if (!success_cf[id]){
new arg[16]
read_argv(0,arg,15)
if (equal(arg,cfg_vforce[position_cf[id]])){
success_cf[id] = 1
remove_task(FORCE_TIMEOUT+id)
return PLUGIN_HANDLED
}
}
return PLUGIN_CONTINUE
}
public client_putinserver(id){
cleanup_action(id)
if (!is_user_bot(id)){
if (cfg_num) do_checking(id,0)
if (cfg_force_num) do_forcing(id,0)
}
return PLUGIN_CONTINUE
}
public client_disconnect(id){
cleanup_action(id)
return PLUGIN_CONTINUE
}
public gate_cc(id){
if (success_cc[id]==2)
return PLUGIN_HANDLED
new arg[4]
read_argv(1,arg,3)
if (equal(arg,close_code_cc[id])){
if (!success_cc[id])
say_found(id,cfg_check[position_cc[id]])
else if (++position_cc[id] < cfg_num)
do_checking(id,position_cc[id])
else
say_finished(id,"checking")
}
else
say_is_blocking(id)
remove_task(CHECK_TIMEOUT+id)
return PLUGIN_HANDLED
}
public gate_cf(id){
if (success_cf[id]==2)
return PLUGIN_HANDLED
new arg[4]
read_argv(1,arg,3)
if (equal(arg,close_code_cf[id])){
if (success_cf[id])
say_is_blocking(id)
else if (++position_cf[id] < cfg_force_num)
do_forcing(id,position_cf[id])
else
say_finished(id,"forcing")
}
else
say_is_blocking(id)
remove_task(FORCE_TIMEOUT+id)
return PLUGIN_HANDLED
}
public time_out(param[])
say_is_blocking(param[0])
say_is_blocking(id){
new name[32]
get_user_name(id,name,31)
server_cmd("say ^"Player %s is blocking Cfg Checker^"",name)
server_cmd("say ^"Stoped forcing and checking configuration on player %s^"",name)
cleanup_action(id)
}
say_finished(id,action[]){
new name[32]
get_user_name(id,name,31)
server_cmd("say ^"Finished configuration %s on %s^"",action,name)
cleanup_action(id)
}
say_found(id,param[]){
new name[32]
get_user_name(id,name,31)
server_cmd("say ^"Found %s on player %s^"",param,name)
server_cmd("say ^"Stoped forcing and checking configuration on player %s^"",name)
cleanup_action(id)
}
cleanup_action(id){
success_cf[id] = 2
success_cc[id] = 2
position_cc[id] = cfg_num
position_cf[id] = cfg_force_num
remove_task(CHECK_NEXT+id)
remove_task(FORCE_NEXT+id)
remove_task(CHECK_TIMEOUT+id)
remove_task(FORCE_TIMEOUT+id)
}
public set_cc(){
if (cfg_num < MAX_CHECKS){
new arg[32]
read_argv(1,arg,31)
copy(cfg_check[cfg_num],31,arg)
cfg_num++
}
return PLUGIN_HANDLED
}
public set_fc(){
if (cfg_force_num < MAX_FORCES){
new arg[32]
read_argv(1,arg,31)
copy(cfg_force[cfg_force_num],31,arg)
read_argv(2,arg,31)
copy(cfg_vforce[cfg_force_num],31,arg)
cfg_force_num++
}
return PLUGIN_HANDLED
}
public plugin_init(){
register_plugin("Cfg Checker","074","default")
register_clcmd(CHECK_CLOSE,"gate_cc")
register_clcmd(FORCE_CLOSE,"gate_cf")
register_srvcmd("amx_cc_check","set_cc")
register_srvcmd("amx_fc_cfg","set_fc")
server_cmd("exec addons/amx/cfgchkcfg")
return PLUGIN_CONTINUE
}要使用我的世界js插件文件激光塔,首先需要下载安装插件。然后打开你的我的世界游戏,并打开控制台(按下F3),在控制台输入/js <插件文件>即可加载插件,插件文件中会有激光塔等功能,进行相应设置后即可使用激光塔功能。笔记本的话 没法用太多的插件
最起码 一个任务查询插件 或者 矿点 提示这种插件 就够受的
对了 还有DPS统计 这个不建议使用
网上的那些整合包 没法用 都是适用于台式电脑的那种配置
使用插件过程中 插件不断积累数据 笔记本根本就受不了 会很卡
所以建议你 需要什么插件 就下相应的单体
头像 可以用默认的 不建议使用插件
施法条就像LS所说的Quartz
动作条就用B4( Bartender4) 或者炽火动作条 后者比前者占用资源少 功能也相对少一点
战斗信息 建议使用MSBT 这个比较简单明了 占用资源少
美化插件不建议使用了
字体可以修改以下 这个无影响
DPS统计 这个插件 收集数据太多了 不建议使用或者每次战斗完毕都清除数据
任务查询 你可以使用以下 制图大师 全名我记不住了 C打头的 (^__^)
这个连副本掉落都有了
其他小的单体插件就看你具体需要了
有问题可以给我留言
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)