首页
社区
课程
招聘
ArcGIS属性表按列复制
2023-9-11 18:18 2606

ArcGIS属性表按列复制

2023-9-11 18:18
2606

起因

使用ArcGIS[特指ArcMap]查看数据属性表的时候,可以选中单元格,然后Ctrl+C复制单元格内的内容.但是常常想复制某一列属性值,这时Ctrl+C复制出来的是列名称.所以就产生了这个修改的想法.[注:当然可以把属性表导出,然后Excel打开,再复制某列的数据]

第一步 可能的解决方案

使用ArcGIS Engiine写插件来实现.在看到XTools Pro提供了一个可以删除属性表字段的功能[Delete Multiple Fields]之后,对这个方案更有信心了.因为这证明插件是可以获取到用户点击了属性表的哪一个字段

但是打开这个菜单项之后,发现该功能还是得输入要删除的字段

后来也看了些ArcGIS Engine的文档,发现写插件这条路有点难,放弃.

2. 那么我们尝试着逆向一下看看能不能实现这个功能呢

第二步 分析ArcGIS代码

既然涉及到复制到剪切板,那么我们就在SetClipboardData函数处下个断点,查看一下调用堆栈

发现og1200asutablecoreui这么两个特殊的dll.

看了下og1200asu这个dll不是ESRI公司的,进一步百度发现是一个第三方类库[ROGUE WAVE - stringray Objective Grid],孤陋寡闻了.发现这个库官方提供的文档还是非常详细的.从官方下载demo发现是既可以复制单个单元格内容也可以复制某一列的内容,这就更有信心了.从官方demo中找一个文件最小的示例调试了一下发现:不管是复制单个单元格还是一列内容都可以调用CGXGridCore::Copy()这个函数来实现,这个函数是og1200asu.dll的一个导出函数.

同时看了下tablecoreui这个库是ESRI公司的,我们把它拉近IDA里面看一下这一块的代码写了什么内容

1
2
3
4
5
6
7
8
// L7: 获取当前选中的单元格行和列
// L8: 构造一个CGXRange对象
// L9: 将L7获取到的行列信息设置到CGXRange对象中
// L10: 动态调试发现是 CGXGridCore::CopyRange
// 后面发现就是在这个函数里处理的Ctrl+C事件
// 也就是说ESRI接管Ctrl+C事件,只让复制单个单元格
// 好消息是tablecoreui.dll导入了CGXGridCore::Copy这个函数
// 我们只需要在这个函数处调用CGXGridCore::Copy()函数就行了

第三步 如何调用CGXGridCore::Copy函数

我们先来看看原程序是如何调用CGXGridCore::GetCurrentCell的

1
2
3
4
5
6
7
8
// 看一下这三条
7B006136: 894D DC mov dword ptr ss:[ebp-24],ecx
7B006143: 8B4D DC mov ecx,dword ptr ss:[ebp-24]                                  
7B006146: FF15 90D7077B  call CGXGridCore::GetCurrentCell
// 1. 因为这个函数调用方式是thiscall, ecx指向this
// 可以看出这个ecx我们是可以使用的
// 2. 第三条FF15 90D7077B, 7B07D790内的值是095A909C, 这个函数是CGXGridCore::GetCurrentCell[在og1200asu.dll领空内]
// 3. 所以我们可以照猫画虎,在7B006130处修改为 FF15 CGXGridCore::Copy C3 [这里没有考虑该函数的返回值,返回的就是CGXGridCore::Copy的返回值了]

第四步 尝试修改PE

那么我们怎么修改这个 FF15 CGXGridCore::Copy C3. 还是照猫画虎,先看下7B006146这里是怎么做的

1
2
3
4
5
6
// 1. 我们也可以写成FF15 XXXX0A10的格式,其中100AXXXX处保存的是CGXGridCore::Copy函数地址,那么这个XXXX应该是多少呢?
// 1.1 让我们查看一下tablecoreui.dll的导入表
// 1.2 从下面的图得知只需要数一下,CGXGridCore::Copy是第多少个导入函数就行了,最终我们得到地址7B07D8BC
// 2. 文件保存的代码和实际运行的代码不一样,看来地址是经过修正的.我们可能需要修正一下重定位表[其实一直分不清导入表和重定位表]
// 2.1 7B07D8BC保存到文件中就是7B07D8BC - 7AFD0000 + 10000000 = 100AD8BC,我们最终就是要在RVA 36130处修改为FF 15 BC D8 0A 10 C3
// 2.2 接着修改下重定位表以修正RVA 36132处的地址,记得修正重定位表的大小[重定位表处正好有空白,美滋滋]


第五步 按列复制数据

备注

稳定性不保证哇


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞0
打赏
分享
最新回复 (1)
雪    币: 19569
活跃值: (29257)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-9-12 11:13
2
1
感谢分享
游客
登录 | 注册 方可回帖
返回