【问题标题】:P/Invoke call to CreateEnvironmentBlock taking up to 30 seconds?对 CreateEnvironmentBlock 的 P/Invoke 调用最多需要 30 秒?
【发布时间】:2012-04-22 23:52:57
【问题描述】:

我一直在使用来自this CodeProject pageProcessStarter C# 类作为交互式用户从 Windows 服务中启动进程。

我注意到(在运行 Win7 和 XP 的大约 50 台不同计算机上测试代码之后)对 CreateEnvironmentBlock 的 P/Invoke 调用(在 Run 方法中)可能需要长达 30 秒才能返回(有时很快,有时则不然)。

我看到了someone else had this problem, but they were getting an error(对我来说它总是有效的)。

为什么调用CreateEnvironmentBlock 需要这么长时间?


P/Invoke 声明:

[DllImport("userenv.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CreateEnvironmentBlock(out IntPtr lpEnvironment, IntPtr hToken, bool bInherit);


CreateEnvironmentBlock电话:

IntPtr lpEnvironment = IntPtr.Zero;
bool resultEnv = CreateEnvironmentBlock(out lpEnvironment, primaryToken, false);

编辑:附加信息:

  • 不是总是 30 秒 - 它会在几秒到 30 秒之间变化(在不同的计算机上)。

  • procmon 显示一大堆注册表读取到诸如HKLM\System\CurrentControlSet\Control\Session Manager\EnvironmentHKCU\Volatile Environment 之类的键,但没有网络活动

  • 访问域工作站上的域控制器似乎对调用的长度没有影响。

  • perfmon 显示几乎没有 CPU 使用率,只有初始和结束 I/O 峰值:

    此示例中的 CreateEnvironmentBlock 调用大约需要 12 秒。

  • The MSDN documentation 推断对 CreateEnvironmentBlock 的调用不会加载用户的个人资料(而且用户已经登录,因此必须加载他们的个人资料):

    仅在加载用户配置文件时设置用户特定的环境变量,例如 %USERPROFILE%。要加载用户的个人资料,请调用 LoadUserProfile 函数。

【问题讨论】:

  • 这 30 秒听起来很像网络超时。您可以使用 procmon (technet.microsoft.com/en-us/sysinternals/bb896645) 来查看在等待期开始时发生了什么吗?
  • @Gabe: procmon 显示一大堆注册表读取到HKLM\System\CurrentControlSet\Control\Session Manager\EnvironmentHKCU\Volatile Environment 等以检索环境变量,但根本没有网络活动。在域帐户登录的域计算机上进行了测试,没有对域控制器的网络访问。
  • 另外,它并不总是 30 秒。它可以在 5 到 30 秒之间的任何时间,如果它纯粹是由于注册表读取(因为某些计算机/用户比其他计算机/用户具有更多的环境变量),那么这是有道理的,但单独的注册表读取肯定不会花费那么长时间吗?跨度>
  • 这段时间是否有 CPU 或磁盘使用情况?如果是这样,它可能表明注册表读取是罪魁祸首(尽管您的计算机应该能够在这段时间内进行数百万次注册表读取)。另外,访问 DC 会影响通话时间吗?
  • @Gabe:DC 访问似乎对通话时间没有任何影响。我使用 perfmon 检查了 CPU 和 I/O,它显示了 I/O 的初始峰值,然后在其余时间什么都没有(并且没有可见的 CPU 时间)。 (Here's the graph from perfmon - 最后一个峰值是CreateEnvironmentBlock 完成的位置,大约需要 12 秒)

标签: c# performance winapi pinvoke


【解决方案1】:

因为为不同的用户创建环境块需要加载该用户的配置文件。如果您在域控制的机器上,这将加倍慢,因为它需要与网络上的 Active Directory 机器交谈并下载配置文件。

【讨论】:

  • 不,这个答案不正确。 CreateEnvironmentBlock 检索已登录用户的环境变量,该用户的配置文件已加载。这就是将用户令牌传递给 CreateEnvironmentBlock 的原因。
  • @Xenon:登录令牌的存在并不意味着用户的配置文件已经加载。请注意,LoadUserProfile 也接受令牌作为参数。
  • @BenVoigt:哦,确实。但是,CreateEnvironmentBlock 的 MSDN 文档确实推断它不会加载用户配置文件。当我调用CreateEnvironmentBlock 时,我正在为登录到交互式会话的用户传递令牌,因此他们的个人资料应该已经被加载,对吧?
  • @Xenon:在这种情况下,我会说是的,配置文件应该已经作为交互式登录过程的一部分加载。
猜你喜欢
  • 2015-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-06
  • 2012-09-28
  • 2014-02-24
  • 2011-05-02
相关资源
最近更新 更多