假设某个作者强制他的 Windows 应用程序为单实例。有没有办法让这个应用程序成为多个实例(除了在虚拟机中运行或要求作者重写应用程序)?
如果有现成的工具,我很想知道。(我试过 sandboxie 和 Altiris SVS,但没有成功)。
如果没有任何可用的工具,我想编写一个可以让我做到这一点的工具/黑客程序。我正在寻找从哪里开始的指示 - 涉及什么,需要什么技能。我有中等的 C 和 Java 编程技能。
如果无法做到这一点,请解释原因。
编辑:我知道这是个坏主意,但我仍然需要这样做(出于各种原因)。我想要一种适用于任何应用程序且不会引入错误的通用方法。
答案1
许多应用程序检查全局进程列表(使用 EnumProcesses、OpenProcess、GetModuleBaseName 和类似函数)或窗口列表(使用 EnumWindows、EnumChildWindows)。
您可以尝试设置钩子(参见示例 SetWindowsHookEx、CallNextHookEx 等)来钩住来自该应用程序的特定 API 函数调用,并用您的数据替换响应中请求的数据,以欺骗应用程序。
答案2
没有通用的方法,因为不同的应用程序使用不同的方法。许多方法涉及尝试获取某些机器范围(或至少是用户范围)的资源(例如,命名的同步对象、具有众所周知的名称和位置的文件或注册表值)。如果应用程序成功,则只要它运行,它就会保留该资源。如果它因另一个实例已持有该资源而失败,那么它可能会尝试向原始实例发出信号,以便它能够做出响应。
在 16 位 Windows 中,当程序启动时,操作系统会向其传递一个称为 HINSTANCE 的唯一句柄。它还会传递使用相同可执行文件(如果有)的当前正在运行的进程的 HINSTANCE。在那些日子里,这可能是程序了解副本是否已在运行的最常见方式。在 32 位 Windows 中,由于内存受保护、进程特定的地址空间以及协作式多任务的结束,HINSTANCE 不再具有相同的含义。
少数应用程序这样做只是为了“可用性”,但对于许多其他应用程序来说,强制使用单例可能是有充分理由的。绕过这一点可能会导致数据损坏或根本无法运行。
答案3
您可以在不同的用户帐户上运行应用程序,并且实例检查将不再起作用。
答案4
在 Windows 8 及更新版本中,按住 Shift 键并单击任务栏上的程序图标/按钮。这将再次启动可执行文件。如果应用程序没有自行检查克隆,您将看到一个新窗口。
如果它打开例如内部 sqlite 文件,这当然可能会与应用程序内部文件产生冲突,所以你必须真正知道自己在做什么,否则就不要介意是否出现问题。