2012-04-22 3 views
2

Я использовал класс ProcessStarter C# от this CodeProject page, чтобы начать процесс как интерактивный пользователь из службы Windows.P/Invoke вызов CreateEnvironmentBlock, занимающий до 30 секунд?

Я заметил (после тестирования коды на ~ 50 разных компьютеров, работает как Win7 и XP), что P/Invoke вызова CreateEnvironmentBlock (в методе 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); 

EDIT: Дополнительная информация:

  • Это не всегда 30 секунд - она ​​меняется (на разных компьютерах) от нескольких секунд до 30 секунд.

  • procmon показывает целый букет реестра читает такие ключи, как HKLM\System\CurrentControlSet\Control\Session Manager\Environment и HKCU\Volatile Environment, но нет сетевой активности.

  • Доступ к контроллеру домена на рабочей станции домена, по-видимому, не имеет никакого отношения к длительности вызова.

  • perfmon показывает практически без использования процессора, и только начальный и конечный/шип O I:

    perfmon graph

    CreateEnvironmentBlock вызова в данном примере потребовалось приблизительно 12 секунд.

  • The MSDN documentation делает вывод, что вызовы CreateEnvironmentBlock сделать не загрузки профиля пользователя (а пользователь уже зарегистрирован в любом случае, так должно быть загружено их профиль):

    пользователем конкретных переменных окружения, таких как % USERPROFILE% устанавливаются только при загрузке профиля пользователя. Чтобы загрузить профиль пользователя, вызовите функцию LoadUserProfile.

+1

Это 30 секунд звучит очень много, как сетевой тайм-аут. Можете ли вы использовать procmon (http://technet.microsoft.com/en-us/sysinternals/bb896645), чтобы узнать, что происходит в начале этого периода ожидания? – Gabe

+0

@Gabe: procmon показывает, что целая куча реестра читает 'HKLM \ System \ CurrentControlSet \ Control \ Session Manager \ Environment',' HKCU \ Volatile Environment' и т. Д. Для извлечения переменных среды, но вообще не работает в сети. Протестировано, что на компьютере домена с учетной записью домена зарегистрирован, без сетевого доступа к контроллеру домена. – Xenon

+0

Кроме того, это не всегда 30 секунд. Это может быть где-то между 5 и 30 секундами, что имеет смысл, если это связано исключительно с чтением реестра (поскольку на некоторых компьютерах/пользователях есть больше переменных среды, чем у других), но, безусловно, чтение в режиме чтения не займет много времени? – Xenon

ответ

0

Поскольку Создание блока среды для другого пользователя требует загрузки профиля для этого пользователя.Если вы находитесь на машине с управлением под доменом, это будет вдвойне медленнее, потому что для этого требуется поговорить и загрузить профиль с вашей машины Active Directory в сети.

+0

Нет, этот ответ неверен. 'CreateEnvironmentBlock' извлекает переменные среды для уже зарегистрированного пользователя, у которого профиль уже загружен. Вот почему токен пользователя передается в «CreateEnvironmentBlock». – Xenon

+0

@ Xenon: Существование токена входа не означает, что профиль пользователя уже загружен. Обратите внимание, что 'LoadUserProfile' также принимает токен в качестве параметра. –

+0

@BenVoigt: Да, действительно. Однако документация MSDN для 'CreateEnvironmentBlock' делает вывод о том, что он не загружает профиль пользователя. Когда я вызываю 'CreateEnvironmentBlock', я передаю токен для входа пользователя в интерактивный сеанс, так что их профиль _should_ уже загружен, правильно? – Xenon