跳转到主要内容

去教育版戳记源码(ARX,LISP版)

去教育版戳记源码(ARX,LISP版)

CAD教育版戳记有时候很讨厌,一旦图中有这个戳记,就会传染到其它图中。就是说从有戳记的图中拷贝到没戳记的,没戳记的也会带上。

而且这个戳记不太好消除。

对于2015-2018,Autodesk公司似乎已经把这个戳记移除掉了,也就是说,用这些版本的CAD打开图,看不到戳记,也不会弹出那个戳记警告框。

保存之后,图中不会再有了(这点我没有每个版本验证)。但该死的是到了2019后,这个又出现了,不知道autodesk公司在玩什么。

关于去教育版有很多方式,ARX的方式最有效。我这里提供用了ARX源码。以及附带的生成的ARX程序。

这个程序的源码 是从网上的 wdzhangsl 引申过来,特此深表感谢!

程序的原理是从数据库指针找到戳记的偏移地址,修改此处的值,便达到了消除。

因为原代码有些重复和繁琐,特此精简,并且升级到2019。经过测试,程序有效。

因为有些CAD版本我是没办法在自己机器安装,就没有一个个CAD版本进行测试其中的偏移地址。

如果有网友能测试到我程序中没有的CAD版本的值,请告诉我或者跟帖。多谢!

下面是程序的源码和已经编译好二进制文件的压缩包。欢迎各位捉虫子和提出建议。

程序的用法是:加载后,程序会自动消除戳记,也可以用手动输入命令QJYB 来消除。

如果你把此程序加载到启动组,以后每当打开有教育版的dwg后,程序会自动消除,你需要做的仅仅是保存文件而已。

对于LISp版本,更有这两项突出功能:

1、消除打开戳记文件的错误警告框。

2、全面兼容各种CAD版本。

LISP的代码如下:(需要DynamicWrapperX支持)

 

ARX的核心代码如下:

#include "stdafx.h"
#include "GetProcess.h"
#include "GetFunctionAddress.h"
#include "RemoveEDU.h"
 
byte OffsetAddress32[6][6]={
	{0xa4,0x06,0xa4,0x06,0xa4,0x06},//R15
	{0xd4,0x06,0xd4,0x06,0xd4,0x06},//R16
	{0xdc,0x07,0x24,0x08,0x34,0x08},//R17
	{0x6c,0x08,0x74,0x08,0x7c,0x08},//R18
	{0x84,0x08,0x84,0x08,0x84,0x08},//R19
	{0x84,0x08,0x84,0x08,0x84,0x08},//R23
};
byte OffsetAddress64[4][6]={
	{0x18,0x0b,0x18,0x0b,0x18,0x0b},//R17
	{0x80,0x0b,0x88,0x0b,0x90,0x0b},//R18
	{0xa8,0x0b,0xb0,0x0b,0xb8,0x0b},//R19
	{0xa0,0x0b,0xa0,0x0b,0xa0,0x0b},//R23
};
 
int RemoveEducationStamp(WNDINFO & wi)
{
	if (wi.ActiveDoc==NULL)
		return FALSE;
	int ret = FALSE;
    CAcadUtility uti=wi.ActiveDoc.get_Utility();
	//获取isEMR函数的RVA地址
	INT_PTR offsetAddr = 0;
	LPCSTR funcName = wi.is64bit ? "?isEMR@AcDbDatabase@@QEBA_NXZ" : "?isEMR@AcDbDatabase@@QBE_NXZ";
 
	HMODULE hDLL = LoadLibraryEx(wi.strAcDbPath,0,DONT_RESOLVE_DLL_REFERENCES);// 
	LPVOID pIsEMR = GetProcAddress(hDLL,funcName);
	FreeLibrary(hDLL);
	if (pIsEMR == NULL)
	{
		pIsEMR = LoadFuncBase(wi.strAcDbPath,funcName,hDLL);
	}
 
	if (pIsEMR == NULL)
	{
		FUNCTION_ADDRESS funcSet;
		ret = getFuncAddr(wi.strAcDbPath,funcSet);
		FUNCTION_ADDRESS::iterator itr = funcSet.find(funcName); 
		if (itr == funcSet.end())
		{
			uti.Prompt(_T("找不到教育版相关函数!可能需要以管理员身份运行此程序,或者CAD版本是2015-2018.\n"));
			return FALSE;
		}
		offsetAddr = itr->second;
		pIsEMR = LPVOID((INT_PTR)wi.hAcDb + offsetAddr); //操纵数据库
	}
	else
	{
		offsetAddr = (INT_PTR)pIsEMR - (INT_PTR)hDLL;
		pIsEMR = LPVOID((INT_PTR)wi.hAcDb + offsetAddr); //操纵数据库		
	}
 
	//以写的方式打开CAD进程
	//HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, wi.dwProcessId); //权限要求太高,可能在某些机器上运行不了
	HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE, FALSE, wi.dwProcessId);
	if (hProcess == NULL)
	{
		uti.Prompt(_T("无法打开CAD进程写入!\n"));
		return FALSE;
	}
 
	const DWORD bWritten = 128;
	byte pEAX = 0;
	SIZE_T dwNumberOfBytes = 0;
 
	CString strTemp = wi.strVersion.Mid(1,2);
	int nMajorVersion = _ttoi(strTemp.GetBuffer());
	if (nMajorVersion>22) 
		nMajorVersion-=3;
	strTemp = wi.strVersion.Mid(4,1);
	int nMinorVersion = _ttoi(strTemp.GetBuffer());
 
	if (wi.is64bit)
	{
		byte AsmCode[15] = {0x48,0x8B,0x49,0x08,0x33,0xC0,0x89,0x81,0x00,0x00,0x00,0x00,0x3C,0x00,0xC3};
		nMajorVersion = nMajorVersion-17;
		AsmCode[8]=OffsetAddress64[nMajorVersion][2*nMinorVersion];
		AsmCode[9]=OffsetAddress64[nMajorVersion][2*nMinorVersion+1];
		ret = WriteProcessMemory(hProcess,pIsEMR,AsmCode,sizeof(AsmCode),&dwNumberOfBytes);
	}
	else
	{
		byte AsmCode[14] = {0x8B,0x49,0x04,0x33,0xC0,0x89,0x81,0x00,0x00,0x00,0x00,0x3C,0x00,0xC3};
		nMajorVersion = nMajorVersion-15;
		AsmCode[7]=OffsetAddress32[nMajorVersion][2*nMinorVersion];
		AsmCode[8]=OffsetAddress32[nMajorVersion][2*nMinorVersion+1];
		ret = WriteProcessMemory(hProcess,pIsEMR,AsmCode,sizeof(AsmCode),&dwNumberOfBytes);
	}
 
	if (!ret)
	{
		uti.Prompt(_T("修改内存模式失败!\n"));
	}
	else
	{
		wi.isRemoved = true;
	}
 
	CloseHandle(hProcess);
	return ret;
}

分类