小编Oli*_*sen的帖子

同步两个相关对象列表的标准算法是什么?

我很确定这必须在某种教科书中(或者更有可能在所有这些教科书中)但我似乎使用了错误的关键词来搜索它...... :(

我在编程时遇到的一个反复出现的任务是我正在处理来自不同来源的对象列表,我需要以某种方式保持同步.通常有一些"主列表",例如由一些外部API返回,然后是我自己创建的对象列表,每个对象都与主列表中的对象相对应(想想"包装"或"适配器" - 它们通常包含扩展信息关于特定于我的应用程序的外部对象和/或它们简化了对外部对象的访问.

所有问题实例的硬特征:

  • 主列表的实现对我来说是隐藏的; 它的界面是固定的
  • 两个列表中的元素不是赋值兼容的
  • 我完全可以控制从属列表的实现
  • 我无法控制主列表中元素的顺序(即它不可排序)
  • 主列表要么根本不提供有关添加或删除元素的通知,要么通知不可靠,即同步只能按需发生,而不是直播
  • 只需在需要时从头开始清除和重建从属列表不是一个选项:
    • 初始化包装器对象应该被认为是昂贵的
    • 其他对象将保存对包装器的引用

在某些情况下的其他特征:

  • 主列表中的元素只能通过读取其属性来识别,而不是通过索引或内存地址直接访问它们:
    • 刷新后,主列表可能会返回一组全新的实例,即使它们仍然代表相同的信息
    • 访问主列表中元素的唯一接口可能是顺序枚举器
  • 大多数情况下,主列表中元素的顺序是稳定的,即新元素总是在开头或结尾添加,而不是在中间; 但是,删除通常可以在任何位置进行

那么我通常如何解决这个问题呢?我应该google算法的名称是什么?

在过去,我已经以各种方式实现了这一点(参见下面的示例),但总觉得应该有更清洁,更有效的方式,尤其是不需要两次迭代的方法(每个列表一个).

这是一个示例方法:

  1. 迭代主列表
  2. 查找"从属列表"中的每个项目
  3. 添加尚不存在的项目
  4. 以某种方式跟踪两个列表中已存在的项目(例如,通过标记它们或保留另一个列表)
  5. 完成后,迭代从属列表并删除所有未标记的对象(请参阅4.)并再次清除所有其他对象

更新1 感谢您的所有回复!我需要一些时间来查看链接.
[...] (文字移至问题主体)

更新2 将中间段重构为(希望)更易于解析的项目符号列表,并在第一次更新中添加后续添加的详细信息.

language-agnostic algorithm synchronization list

27
推荐指数
3
解决办法
7583
查看次数

将Inno Setup安装程序包装在MSI中以便通过AD更容易分发是否可行/明智?

我们的安装程序是用Inno Setup编写的,我们对它非常满意.然而,一些客户不断要求MSI安装程序,他们可以通过Active Directory更轻松地分发.我们已经花了一些时间,通过/LOADINF使用我们自己的选项扩展Inno Setup的机制,使安装程序与自动化和无人值守安装相得益彰.

为了满足客户要求MSI,我一直在考虑简单地将我们的常规安装程序包装在MSI中,可能是使用WIX创建的.问题是:我可以保持当前安装程序提供的高可配置性吗?在无人值守/大规模安装方案中,如何通过外部MSI公开Inno Setup安装程序的选项?

请注意,我还没有真正深入到实际挖掘MSI创建和WIX的程度.现在我只关心那些知道他们在说什么的人认为这是一种可行/合理的方法来投入我们的能量......

[编辑:]最初我认为我可以使用临时提取和执行方法,即MSI只是用作将Inno安装程序交付到目标PC并在其中以/VERYSILENT-mode 执行的容器.但我想要求MSI的客户也希望能够从中央位置卸载甚至修改安装,我想在那种情况下这是不可能的,不是吗?

PS:我们在这里也有一份WISE for MSI的旧版本,但这种体验实际上就是为什么我们开始使用Inno来开始...

windows-installer inno-setup

25
推荐指数
2
解决办法
1万
查看次数

EnumWindows返回句柄的顺序是否有意义?

从几个初步测试开始,似乎EnumWindows总是以反向实例化顺序返回窗口,即最近实例化的窗口.这是一个有效的观察吗?如果是这样,在所有版本的Windows中都是如此吗?这是一个可靠的假设,即某种行为记录在哪里?


上下文:我正在处理我触发第三方应用程序打开几个非模态窗口的情况,我需要在打开后向这些窗口发送一些窗口消息,但我没有确定的方式鉴定它们的窗口类别和它们的标题都不会有所不同,我也不知道它们的预期坐标.但是,如果我可以依赖上面的行为,EnumWindows我可以简单地使用返回的第一个句柄,EnumWindows其类和标题符合我的期望.这仍然留下一些假设的循环漏洞,但我认为这将是足够好的.尽管如此,欢迎另类建议.

windows winapi enumeration hwnd

19
推荐指数
1
解决办法
5391
查看次数

什么可以导致Outlook将COM-addin的LoadBehavior更改为2 - 除了未处理的异常?

几个星期以来,我们一直在努力解决一个问题,即少数客户的Outlook插件因未确定的原因而被卸载和禁用."禁用"是指Outlook将以下注册表值从3更改为2,这实际上意味着下次启动时不会加载该插件:

HKEY_LOCAL_MACHINE\Software\Microsoft\Office\Outlook\Addins\[OurAddin.sProgID]\LoadBehavior

没有错误消息,也没有任何异常显示在我们的addin生成自己的日志文件中.

我已经找到以下专门处理LoadBehavior更改问题的页面:http://blogs.msdn.com/vsod/archive/2008/04/22/Troubleshooting-com-add-in-load-failures.aspx

但是,那里提出的任何可能的理由似乎都不适用:

  • 插件不仅列在"禁用项目"列表中.
  • IDTExtensibility2方法中和代码中的任何其他地方都没有未处理的异常.所有代码都包含在try/catch等效项中,并且所有异常输出仅通过OutputDebugString日志文件发送或发送到日志文件中.
  • 该错误似乎与防病毒软件无关,即它也会在禁用时发生.
  • 禁用所有其他插件也不会对错误产生影响.

那么,还有什么可以导致Outlook禁用插件?

更多细节/观察:

  • 到目前为止,我们无法在测试环境中重现该问题,因此在问题发生时我们尚未能附加调试器.
  • 当我们尝试通过远程支持(TeamViewer)观察会发生什么时,问题永远不会发生.我怀疑这是因为TeamViewer使用了一个钩子DLL,它将自身注入到所有正在运行的进程(包括Outlook)中,从而影响内存布局,时序,线程顺序等等.
  • 每当我们编译新版本的插件以尝试新的东西时,插件通常可以正常工作几个小时甚至几天,最终再次被禁用.一旦发生这种情况,所有后续尝试在该机器上加载插件(通过手动更改LoadBehavior值)将失败(即LoadBehaviour将简单地改回2),直到我们编译和部署另一个版本(或尝试使用TeamViewer - 见上文).
  • 通常,插件将在Outlook启动时立即卸载,但偶尔也会在Outlook运行一段时间后发生.在这些情况下,日志文件看起来完全不可靠 - 插件只是经历了常规关机步骤,就像Outlook正常关闭一样.
  • 据我所知,从我们的日志文件和通过SysInternals ProcessMonitor观察问题,当在Outlook启动时(而不是在会话期间)禁用插件时,即使在COM对象(即插件)实例化之前,DLL也会被卸载(构造函数中的日志消息永远不会显示).
  • 我们已将OutputDebugString消息放入initialization部分(这是一个Delphi DLL).当插件无法加载时,它们都不会出现.
  • 只有极少数客户受此问题影响.我们有数万个安装,我们没有收到任何关于此的报告.

  • 更新:似乎经常(但不总是)在addin被卸载之前记录的最后一件事是文本"OLE错误800A01A8"的异常.该异常被我正在使用的框架(Add-in-Express)中内置的全局异常处理程序捕获,并且看起来并不是源自我自己的代码,而现在每个方法完全包含在其中try..catch.这通常发生在我从Inspector的Activate事件处理程序设置我的CommandBarButtons的可见性之后.

所有受影响机器的共同属性:

  • Windows XP Professional,最新的补丁级别
  • Outlook 2003 Professional,最新的修补程序级别
  • 不同版本的McAfee Virus Scan(虽然禁用它没有效果 - 见上文)
  • 用户是本地Administrators组的成员

还有一点需要注意的是,这可能也很重要(尽管可能没有我想象的那么多):
我们正在使用来自第三方供应商的许可/复制保护模块,该模块将已编译的DLL包装在"shell"中,并且仅在运行时解包.自从我发现即使在我们自己的代码被执行之前,addin被卸载,这一直是我的主要嫌疑人.但是,虽然供应商确认其代码中可能存在未处理的异常,但是由保护shell的特殊调试版本生成的日志文件显示解包过程已成功完成,并且在Outlook卸载插件之前控件已经传回受保护的DLL .因此,无论是什么导致Outlook卸载我们的插件都发生在保护shell初始化完成和我们自己的代码之间.

还有什么想法吗?

outlook add-in exception-handling exception

18
推荐指数
2
解决办法
4万
查看次数

如何调试仅在应用程序关闭时发生的崩溃?(DELPHI)

因此,在最近的一些更改后,我们发现我们最老的应用程序之一有时会在关机时崩溃.这表现为"运行时错误216"消息的形式,或者来自Windows错误报告的消息,表明应用程序已停止工作.该应用程序已经OutputDebugString在每个回合发出消息,AFAICT我们自己的所有代码都正确执行完成.所有析构函数都被称为所有终结部分和类析构函数,其中没有一个会引发任何异常.

此外,madExcept和FastMM4的完全调试模式似乎都没有什么可抱怨的(尽管这可能是一个错误的结论,因为甚至在这些组件自己的终结代码运行之前就可能发生崩溃).

那么,你会做什么?你会从哪里开始的?


这个问题应该更多地关于这类问题的一般方法,而不是我目前面临的具体实例,所以我故意遗漏细节.请随意询问您是否认为它们可能与调试方法的选择相关,我稍后会添加它们.

delphi crash debugging application-shutdown

13
推荐指数
3
解决办法
6240
查看次数

我需要做什么才能使我的WH_SHELL或WH_CBT钩子程序从其他进程接收事件?

我正在尝试使用SetWindowsHookEx设置一个WH_SHELL钩子来获得系统范围HSHELL_WINDOWCREATEDHSHELL_WINDOWDESTROYED事件的通知.我传递0作为最终dwThreadId参数,根据文档,它应该"将钩子过程与在与调用线程相同的桌面上运行的所有现有线程相关联".我也将参数传递给我的DLL(HInstance在Delphi中),hMod就像我看到的所有例子一样.

然而,我只收到由我自己的应用程序创建的窗口的通知 - 通常情况下 - 我的测试导致桌面进程在关闭我的应用程序后熄火.在你问之前,我打电话UnhookWindowsHookEx.我也经常CallNextHookEx在我的经纪人内部打电话.

我正在从一个有限的用户帐户运行我的测试应用程序,但到目前为止我还没有找到任何提示,表明这将起作用...(虽然这实际上让我感到惊讶)

AFAICT,我按书完成了一切(显然我没有,但到目前为止,我没有看到哪里).

我正在使用Delphi(2007),但我认为这不应该真的重要.

编辑:也许我之前应该提到这个:我确实下载并尝试了几个例子(尽管很遗憾没有那么多可用于Delphi - 特别是没有用于WH_SHELL或者WH_CBT).虽然它们不会像我的测试应用程序一样崩溃系统,但它们仍然不会捕获来自其他进程的事件(即使我可以使用ProcessExplorer验证它们是否可以加载到它们中).所以我的系统配置似乎有问题,或者示例错误,或者根本无法从其他进程捕获事件.任何人都可以开导我吗?

编辑2:好的,这是我的测试项目的来源.

包含钩子过程的DLL:

library HookHelper;

uses
  Windows;

{$R *.res}

type
  THookCallback = procedure(ACode, AWParam, ALParam: Integer); stdcall;

var
  WndHookCallback: THookCallback;
  Hook: HHook;

function HookProc(ACode, AWParam, ALParam: Integer): Integer; stdcall;
begin
  Result := CallNextHookEx(Hook, ACode, AWParam, ALParam);
  if ACode < 0 then Exit;
  try …
Run Code Online (Sandbox Code Playgroud)

windows delphi hook winapi

12
推荐指数
1
解决办法
4954
查看次数

你如何处理trac中的多个(重叠)项目?

我们正在使用trac并且对它非常满意.但是,开箱即用,trac最适合单项目环境.我有兴趣了解人们采取的各种方法,以使其与多个项目一起工作,以及他们的经验.有推荐的插件吗?任何补丁,调整或诸如此类的东西?您是否甚至可以使用完全不同的错误跟踪系统来提供所有trac的功能以及多项目支持?

我们最近开始自己管理第二个项目,这通常可以正常工作但也有一些缺点,特别是在两个项目重叠的情况下,因为我们编写的公共库代码在两个项目中都使用.你怎么处理这个?

(我将附上我们自己当前的方法作为这篇文章的答案.)

trac multi-project

11
推荐指数
1
解决办法
4590
查看次数

Delphi:为什么我有时会使用此代码获得I/O错误103?

在我的几个应用程序中,我的代码类似于以下内容:

if ForceDirectories(ExtractFilePath(lLogName)) then
  begin
    AssignFile(lLog, lLogName);
    try
      if FileExists(lLogName) then
        Append(lLog)
      else
        Rewrite(lLog);
      Writeln(lLog, lLogLine);
    finally
      {$I-}CloseFile(lLog);{$I+}
    end;
  end;
Run Code Online (Sandbox Code Playgroud)

在一个应用程序中,第一次尝试执行此操作时,我一直在使用Append语句的行上获得I/O错误103异常(在调用此文件之前文件确实存在).此操作的所有后续尝试都将正常工作 - 直到我重新启动应用程序.

所有我发现这个错误的文档到目前为止表示,这将通过调用引起CloseFile恕不另行Reset或者Rewrite(Append通常没有提及),或者如果该文件是由另一个进程使用.由于异常发生在调用CloseFile它之前显然不可能是前者.

我已经尝试ResetAssignFilefor good措施之后插入一个权利,但之后我在该行上获得了异常.

也没有其他应用程序直接访问该文件.我说的"阳谋",因为我有一个轻微的怀疑,防病毒(TrendMicro的在我的情况)可能是cuplrit这里(所以也许该文件在使用中).如果这确实是问题,那么围绕它的最佳方法是什么?硬编码自动重试对我来说真的不是一个干净的解决方案......


在那里我有时会收到103错误另一种情况是这样的代码,我用它来创建一个空文件(或者更经常清空现有的文件):

AssignFile(lFile, AFileName);
try
  Rewrite(lFile);
finally
  CloseFile(lFile);
end;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,重现起来要困难得多.它发生的次数要少得多.大多数情况下,这似乎是在我重新编译应用程序后的第一次运行时发生的.这可能再次成为反病毒的阻碍吗?我从未见过这种情况发生在我的开发机器上,从未得到过客户的报告.与第一个场景一样,每个应用程序会话只发生一次(如果有的话).后续尝试总是成功的.

有关创建空文件或清空现有文件的其他可能更安全的故障安全方法的建议吗?

delphi file-io

11
推荐指数
2
解决办法
4万
查看次数

如何查询Active Directory对象的有效权限?

我正在尝试以编程方式确定当前用户是否对给定的Active Directory对象具有某些权限(特别是在这种情况下,我正在尝试确定用户是否具有另一个Exchange用户或通讯组列表对象的"代理发送"权限).

我已经想通了如何访问ntSecurityDescriptor使用ADSI属性:我可以在枚举的ACE IADsSecurityDescriptorDiscretionaryACL财产.但:

  • 如何根据该数据确定受托人是否明确允许或拒绝"发送为"许可?
  • 如果通过组成员资格间接授予权限,我该如何发现?我是否真的必须通过(递归)检查用户所属的所有组来自己解析有效权限?当然必须有一个API用于该任务......

FWIW,我使用ActiveDs.dll类型库在Delphi中编码(即本机Win32代码),因此特定于.NET的解决方案对我没有多大帮助,除非他们的源代码为我提供了如何在本机中执行相同操作的线索码.PowerShell也是如此.


在任何人开始之前:我已经知道了PR_EMS_AB_PUBLIC_DELEGATESPR_EMS_AB_PUBLIC_DELEGATES_BL_O扩展的MAPI属性.但是,这不是我追求的.这些属性引用"代表发送"-right(又名委托),而不是"发送为"权限,这是完全不同的事情.

permissions exchange-server adsi active-directory

9
推荐指数
1
解决办法
3465
查看次数

在使用模拟对象时,如何防止单元测试需要有关实现内部的知识?

我还处于关于单元测试的学习阶段,特别是关于模拟(我正在使用PascalMockDUnit框架).我现在偶然发现的一件事是,我找不到将测试类/接口的硬编码实现细节硬编码到我的单元测试中的方法,这只是感觉不对...

例如:我想测试一个实现非常简单的接口的类,用于读取和编写应用程序设置(基本上是名称/值对).呈现给消费者的界面完全不知道实际存储值的位置和方式(例如,注册表,INI文件,XML,数据库等).当然,访问层是由一个不同的类实现的,该类在构造时被注入到测试类中.我为这个访问层创建了一个模拟对象,现在我可以完全测试接口实现类,而无需实际读取或写入任何注册表/ INI文件/任何内容.

但是,为了确保模拟行为与被测试类访问时的真实行为完全相同,我的单元测试必须通过非常明确地定义预期的方法调用和测试类所期望的返回值来设置模拟对象.这意味着如果我必须更改访问层的接口或测试类使用该层的方式,我还必须更改内部使用该接口的类的单元测试,即使接口我实际上测试的类没有改变.这是我在使用模拟时必须要使用的东西,还是有更好的方法来设计避免这种情况的类依赖性?

oop unit-testing mocking dunit pascalmock

8
推荐指数
2
解决办法
546
查看次数