Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,如果要生成各种报告基本非他莫属。

Aspose Total for Java 已有成熟方案,但 .NET/Python 现有方法基本已经失效。

本质上Python版本还是调用的.NET,所以只要解决.NET也就解决Python的问题。

还有另外一个原因就是dotnet已经支持自包含,所以应用可以完全脱离dotnet的运行时独立运行。

本文测试版本23.3.0

调试

学习很多前辈的文章,发现都反混淆后分析流程,难度非常大

经过观察发现,Aspose会通过反射的方式调用系统类库,所以只需要在反射处下一个日志记录断点

记录调用的类、方法、参数等信息

编写一个Aspose的helloworld,通过一个过期的授权观测流程,用dnspy调试

  1. 断点位置System.Private.CoreLib.dll!System.Reflection.MethodBase.Invoke(object obj, object[] parameters)

  2. 日志断点打印的表达式{a.DeclaringType.FullName}.{a.ToString()}({b},{c[0]},{c[1]},{c[2]})

invoke

分析

过期时间解析

根据日志可以找到过期时间解析的调用,因为20200827恰好我们这个授权的过期时间

1
21:43:38.386 "System.DateTime"."System.DateTime ParseExact(System.String, System.String, System.IFormatProvider)"(null,"20200827","yyyyMMdd",{})

授权产品获取

根据日志,可以找到授权产品获取的关键点,我们的授权中产品是Aspose.Total for .NET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
21:43:37.265 "System.Xml.XmlNodeList"."System.Xml.XmlNode get_ItemOf(Int32)"({System.Xml.XmlElementList},0x00000000)
21:43:37.298 "System.Xml.XmlNode"."System.String get_InnerText()"({Element, Name="Product"})
21:43:37.319 "nBb"."System.String a(Int32)"(null,0xB8B6DED8)
21:43:37.341 "System.String"."Boolean op_Equality(System.String, System.String)"(null,"Aspose.Total for .NET","Aspose.Word")
21:43:37.362 "nBb"."System.String a(Int32)"(null,0xB8B6DEC6)
21:43:37.383 "System.String"."Boolean op_Equality(System.String, System.String)"(null,"Aspose.Total for .NET","Aspose.Excel")
21:43:37.404 "nBb"."System.String a(Int32)"(null,0xB8B6DEB3)
21:43:37.425 "System.String"."Boolean op_Equality(System.String, System.String)"(null,"Aspose.Total for .NET","Aspose.Excel.Web")
21:43:37.446 "nBb"."System.String a(Int32)"(null,0xB8B6DE9C)
21:43:37.467 "System.String"."Boolean op_Equality(System.String, System.String)"(null,"Aspose.Total for .NET","Aspose.PowerPoint")
21:43:37.488 "nBb"."System.String a(Int32)"(null,0xB8B6DE84)
21:43:37.509 "System.String"."Boolean op_Equality(System.String, System.String)"(null,"Aspose.Total for .NET","Aspose.Project")
21:43:37.555 "nBb"."System.String a(Int32)"(null,0xB8B6DF9F)
21:43:37.578 "System.String"."Boolean op_Equality(System.String, System.String)"(null,"Aspose.Total for .NET","Aspose.Total for .NET")

破解

过期时间

patch System.DateTime ParseExact(System.String, System.String, System.IFormatProvider)

1
2
3
4
if (s == "20200827" && format == "yyyyMMdd")
{
return new DateTime(3155378975999999999L); // 表示9999/12/31 23:59:59
}

授权产品

patch System.Xml.XmlNode System.Xml.XmlNode get_ItemOf(Int32)

当授权产品是Aspose.Total表示全架构全平台授权,如果只使用dotnet版本这个patch可以不做。

1
2
3
4
5
6
7
8
XmlNode xmlNode = this.Item(i);
if (xmlNode.InnerText == "Aspose.Total for .NET")
{
XmlElement xmlElement = new XmlDocument().CreateElement("Product");
xmlElement.InnerText = "Aspose.Total";
return xmlElement;
}
return xmlNode;

dotnet自包含

  1. 先替换patch后的系统文件
  2. 然后修改项目的csproj文件
  3. 最后通过dotnet publish -r linux-x64 -c Release

最终就可以编译出脱离dotnet独立执行的可执行文件了,编译后文件大小33M,非常完美

csproj文件,如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<PublishTrimmed>true</PublishTrimmed>
<DebuggerSupport>false</DebuggerSupport>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Aspose.Words" Version="23.3.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.80.1" />
<TrimmerRootAssembly Include="Aspose.Words" />
<TrimmerRootAssembly Include="mscorlib" />
</ItemGroup>
</Project>