1

我有一个旧的 VW3/ENVY 图像,其中一个包裹作为非托管代码加载(正是Mastering ENVY/DEVELOPER警告的情况)。不幸的是,这个问题发生在很久以前,在没有加载包裹的情况下“返回”到图像已经太晚了。

显然,有一种方法可以解决这个问题(我们有一个开发映像已经解决了这个问题,并且有正常的配置映射包含与非托管包裹完全相同的代码,但它们无法加载),但确切的方式早已被遗忘(并且将特定的开发映像作为新运行时映像的基础存在一些问题,因此我需要找出如何再次执行此操作)。

理论上,应该可以从配置图中移除包裹并重新加载代码。在实践中,所有正常方式(使用 ParcelBrowser 或直接调用 UnmanagedCode>>remove)都会失败。我什至尝试从方法字典中手动删除有问题的选择器,但过了某个点(涉及调用#primBecome:)整个图像完全挂起(我什至无法进入调试器)。我开始破解类和方法的实例,希望我能欺骗 ENVY,让他们认为这些特定的方法是正常的版本化代码,但还没有成功。

周围是否有任何 smalltalk/envy 大师仍然记得足够多的 VW 3 来为我提供任何指示?

状态更新 经过一周的尝试解决问题后,我终于做到了,至少部分做到了,所以以防万一有人感兴趣......

首先,我必须修复未管理代码的文件指针(否则,所有试图触及方法的所有内容都会引发异常)。看起来 ENVY 扩展了 Parcel,因此理论上,所有整数文件指针void在加载时都会更改为 ENVY 的文件指针,但在我的情况下,我必须手动完成(Parcel 为其定义的所有选择器提供枚举)。另一种方法是调整filePointer代码,但这不容易在需要的每个图像上自动完成。

然后,可以丢弃包裹,丢弃包裹信息,但保留代码。官方的“丢弃”机制需要有一个有效的更改文件(envy 不使用它,因此必须手动设置,然后重新设置)和包源(幸运的是我们有)。

为了能够对方法进行任何更改(手动或通过从 ENVY 加载应用程序或类),他们需要摆脱其非托管状态。这可以通过手动调整来完成TheClass>>applicationAssocs(我还删除了对 UnmanagedCode sich 中类的所有引用作为时间戳,并删除了对丢弃包裹的引用)。我实际上从我的老板那里得到了一些关于如何达到这一点的信息,但是直到我自己几乎想通了,我才能够理解这些指示。

这最终允许我加载和重新加载所有包含这些类的应用程序。理论上。实际上,每当我尝试加载较新版本的应用程序(包含以前在包中的代码)时,图像仍然完全挂起。

事实证明,崩溃与不受管理的代码完全无关,而是与相关包裹已修改的事实有关,由于缺少和/或未初始化的类变量(该方法未调用)InputState>>process:而导致异常InputState>>initialize直到新process:方法到位之后)。我不得不修改Notifier类以将所有异常转储到文件中以找出发生了什么。将类变量添加到类的源(而不是通过反射添加),通过挂起输入处理线程toBeLoadedCode并在loaded方法中重新启动它并创建新版本的应用程序甚至解决了这个问题。

现在一切正常,理论上。实际上它仍然无法使用,因为重新加载 WindowSystem 或 VisualworksBase 应用程序会导致它们的初始化块运行,并且很多设置都被重置为默认值 - 字体和字体大小、窗口颜色、UI 设置......而且没有似乎可以将设置保存到文件并稍后加载它们,或者只是查看所有设置是什么(官方设置菜单没有显示所有内容,或者我们有一个经过大量调整的图像......这么多从头开始重建它)。但这是一个完全不同的问题。

4

1 回答 1

1

好吧,通常建议您应该能够通过从存储库加载代码来从头开始重建开发映像。但如果你有这个,那么答案很简单,只需丢弃该图像并重新加载。我认为已经足够长的时间了,以至于我已经失去了有关如何弄乱内部结构以使其恢复的所有知识,听起来您已经尝试了很多事情。因此,尽管这可能很痛苦,但通过从存储库中加载内容来找出重建开发映像的方法听起来可能是您最好的选择。它可能并不是那么可怕,只是可能对图像状态有一些依赖,或者需要执行特殊的 doit。

您可能还需要根据您正在使用的映像中的内容来验证存储库中的内容。如果加载了非托管代码,然后有人对其进行了修改并保存了它,我不清楚它是否会保存到 ENVY。因此,您可能想要审核所有非托管代码,如果已更改,请将其保存到存储库版本。

抱歉,我没有更好的答案。

于 2009-09-10T19:32:08.320 回答