【发布时间】:2012-04-22 23:52:57
【问题描述】:
我一直在使用来自this CodeProject page 的ProcessStarter 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\Environment和HKCU\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\Environment、HKCU\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