首页 技术 正文
技术 2022年11月8日
0 收藏 584 点赞 2,087 浏览 4257 个字

前言

昨天我发布了NCleaner,一款Dism++清理插件(地址:http://bbs.pcbeta.com/viewthread-1692182-1-1.html

有些人想要我开源NCleaner;我只能说很遗憾,鉴于国内环境,是不可能的。我就说个真实故事吧(其实很悲哀)

曾经,一位大牛写了一个充满了黑科技的软件,在论坛发布并公布了源代码
某天,那位大牛发现某些人修改他的源代码用于商业用途,更可气的是某些人只修改了软件的名字
最终,那位大牛改掉了他的软件名,从此再也不公布主程序源代码
那个软件就是Dism管理器,即Dism++前身

虽然NCleaner闭源,但是我可以写一篇Dism++插件开发教程作为补偿(笑)

虽然我不能保证该教程写的多么生动;但是我会尽力(笑)

Dism++,我只能说这软件真的是非常强大(这只是我个人看法);至于可靠性,你只要不作死开启专家模式那就没问题(笑)

说到Dism++插件开发,其实以前作者提供过SDK(但是很长时间就再也没提供过);上次和作者谈了谈我想开发插件的想法(希望作者可以提供SDK);最终如愿以偿,并发布了NCleaner(用游戏相关话语来说,我也是过了一周目的人)

开发环境

1.  Dism++ 10.1.5.3及以后版本的Dism++(没有Dism++开发Dism++插件是不可能的)
2. 一个可以编译dll的C++编译器,我推荐使用Visual Studio 2015
3. 如果可以的话,最好安装Windows SDK 10.0.10586

Dism++清理插件相关内容科普

首先说下Dism++清理插件函数定义(参考Dism++帮助文档.pdf 68页)

//一个清理插件函数定义
HRESULT WINAPI CleanupPlugin(
_In_ DismSession Session,
  _Reserved_ DWORD Flags,
  _In_opt_ UINT64 *CleanUpSpace,
  _In_ DismCallBack CallBack,
_In_ LPVOID UserData);

DismSession Session
映像会话,可以使用此获取映像的各种信息(可以看作映像会话的句柄)

DWORD Flags
保留,Dism++现在不使用此参数,请忽略

UINT64 *CleanUpSpace
如果 CleanUpSpace 为空,那么函数需要执行清理。
如果不为空,说明仅要预估可清理的空间。最后将预估大小用此变量返回

DismCallBack CallBack
Dism++清理回调函数,用于展示进度,文件路径等信息。
如果此参数为 NULL,则表示没有回调。
回调函数定义参考下一段介绍

LPVOID UserData
回调函数的 UserData 部分,请务必传入 CallBack 中。

返回值: 如果函数执行成功,请返回 S_OK,其他任何值都表示错误

回调函数定义

typedef DWORD(WINAPI *DismCallBack)(
DWORD dwMessageId,
WPARAM wParam,
LPARAM lParam,
PVOID UserData);

回调函数支持以下消息:

DISM_MSG_PROGRESS – 用于反馈处理进度
wParam =当前完成百分比
lParam = 0

DISM_MSG_PROCESS  – 用于在状态栏中展示正在处理的文件路径
wParam = (PWSTR) pszFullPath
lParam = 0

DISM_MGS_RemoveInfo
报告 UI 需要删除的文件,此消息仅扫描时可用,清理时将无视此消息
wParam = 0
lParam = (LPCWSTR) 需要删除的文件路径
Dism++收到此消息后,会将文件路径展示在详细信息中。

我经常使用的Dism++ API介绍(希望对其他人有用)

HRESULT WINAPI DismGetSystemInfoBySession(
DismSession Session,
DismSystem** Info);
该API作用是获取当前映像信息;你会得到DismSystem结构的指针(看Dism++作者对于该结构的说明,我想你们应该都能理解)

HRESULT WINAPI DismFreeMemory(void* pStruct);
切记通过Dism++获得的结构指针需要用该API释放

HRESULT WINAPI DismRegOpenKeyEx(
DismSession Session,
HKEY hKey,
LPCWSTR lpSubKey,
REGSAM samDesired,
PHKEY phkResult);
获取注册表键值,用法类似RegOpenKeyEx

HRESULT WINAPI DismWriteLog(
DWORD LogLevel,
LPCWSTR LogName,
LPCWSTR LogValue);
写入日志,LogLevel定义如下,LogName是日志类别,LogValue是日志内容
DismLogLevelSilent 不输出任何信息
DismLogLevelFailure 仅错误
DismLogLevelWarning 错误和警告
DismLogLevelInformation 错误、警告和信息
DismLogLevelDebug 以上所有内容和调试输出

插件开发注意事项

1. Dism++基于CBS,而CBS是一个COM组件;所以在启动时会自动进行COM初始化;你不需要在清理插件函数中执行COM初始化;切记不要在清理插件函数中调用COM反初始化,否则后果我和Dism++的作者们都不敢想(当然不敢试)
2. 注意DismSystem结构的RootPath的路径类似”C:”,”D:\Image”这样的(在写文件操作代码时需要注意)
3. Dism++的展开环境变量API在离线下会受限
4. Dism++的打开注册表API不支持打开离线映像的HKEY_USERS(Dism++旧版本支持;只是作者在某个版本移除了);HKEY_CURRENT_USER打开的是Default User的注册表

5. 只有返回S_OK,才代表Dism++ API正确执行

插件开发教程

配置好环境,打开Visual Studio;首先新建一个Win32动态链接库项目
接着把Dism++SDK(Dism++目录\Dism++SDK目录中的内容)复制到你的项目目录,并加入你的解决方案

然后你可以在cpp文件中根据前文内容编写你要编写的代码(下面举个例子)

#include <Windows.h>

#include “Dism++API.h”
#include “Plugin.h”
#ifdef _AMD64_
#pragma comment(lib,”Dism++x64.lib”)
#else
#pragma comment(lib,”Dism++x86.lib”)
#endif

// Dism++清理插件开发入门
HRESULT WINAPI TestCleanup(
        _In_ DismSession Session,
        _Reserved_ DWORD Flags,
        _In_ UINT64 *CleanUpSpace,
        _In_ DismCallBack CallBack,
        _In_ LPVOID UserData)
{        
        MessageBoxW(nullptr, L”Hello Dism++”, L”HelloWorld”, MB_ICONINFORMATION);

        return S_OK;
}

顺便你需要建立一个def文件导出你的符号(同样举个例子)

LIBRARY

EXPORTS
TestCleanup

还有你需要编写Dism++的插件配置文件(需要命名为Custom.xml,下面举个例子)

<?xml version=”1.0″ encoding=”utf-8″?>
<Data>
  <CleanCollection4>
    <Item Name=”清理项目名” Level=”2″>
      <Discription>清理项目描述 </Discription>
      <Warning>警告对话框要显示的内容</Warning>
      <Group>清理项目所属组</Group>
      <ScanCollection>  
        <Scan Type=”Custom”>
          <Activate>
            <Custom ProcName=”插件dll对应的导出符号”/>
          </Activate>
        </Scan>
      </ScanCollection>
    </Item>
  </CleanCollection4>
</Data>

和Dism++插件信息文件(需要命名为Info.xml)

<?xml version=”1.0″ encoding=”utf-8″?>
<Data>
  <Plugin>
    <Name>插件名称</Name>
    <Version>填写插件的版本号,例如1.0.0.0</Version>
  </Plugin>
  <Languages>
    <zh>
      <FriendlyName>插件名称(中文)</FriendlyName>
      <Decription>插件注释(中文)</Decription>
    </zh>
    <en>
      <FriendlyName>插件名称(英文)</FriendlyName>
      <Decription>插件注释(英文)</Decription>
    </en>
  </Languages>
</Data>

编译
64位dll需要命名为Plugin.amd64.dll;32位dll需要命名为Plugin.x86.dll

Plugin.amd64.dll , Plugin.x86.dll , Custom.xml , Info.xml这四个文件需要放在一个以 [插件名]_[发布者名称Base64加密密文;发布者名称要求16个字符]目录中,并把该目录复制入Dism++目录\Config\Plugin目录即可

然后开启Dism++就可以进行调试了(VisualStudio->调试->附加到进程)

Demo项目下载(要求VS2015)
http://pan.baidu.com/s/1o8znY7w

结语

最后我得提醒想开发Dism++清理插件的开发者,虽然插件写起来是容易的,但要注意的细节是很多(写本教程时,楼主的体会越发深刻)

如果想获取更多信息,建议加入Dism++官方群(200783396)讨论

毛利

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,023
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,513
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,360
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,143
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,774
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,853