Как запустить PowerShell в WiX с правильным доступом к реестру Windows?

Обновить

Интересно, что если я запускаю 32-битную PowerShell для запуска скрипта, это выдает мне ту же ошибку. Похоже, у 32-битного PowerShell нет доступа к 64-битному дереву реестра? Я пытался с помощью WixQuietExec64 но это дало ту же ошибку. Я также попытался указать полный путь к PowerShell (C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe) чтобы убедиться, что установщик запустил 64-битную версию, но STILL выдал ту же ошибку... Похоже, это могло быть вызвано тем, что сам установщик MSI был 32-разрядным??

MSI (s) (4C:C0) [14:25:49:955]: Hello, I'm your 32bit Elevated Non-remapped custom action server.

Оригинальный пост

У меня есть следующее test.ps1 сценарий:

$exchangeroot = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\"
$allexchanges = Get-ChildItem -Path Registry::$exchangeroot -Name | Where-Object { $_ -match "^V.." }
$sorted = $allexchanges | Sort-Object -descending
If ($sorted.Count -gt 1) { $latest = $sorted[0] } Else { $latest = $sorted }
$setup = $exchangeroot + $latest + "\Setup"
$properties = Get-ItemProperty -Path Registry::$setup
$properties

Запуск сценария в обычных окнах PowerShell приводит к следующему выводу:

PS C:\Program Files (x86)\TrustValidator Exchange Server Plugin> .\test.ps1

Required machine-level settings.          : 1
Services                                  : C:\Program Files\Microsoft\Exchange Server\V15
NewestBuild                               : 10845
CurrentBuild                              : 710737954
Information Store Service                 : 1
Messaging and Collaboration Event Logging : 1
MsiInstallPath                            : C:\Program Files\Microsoft\Exchange Server\V15\
...

Так что это работает. Теперь, запустив PowerShell из установщика WiX и выполнив сценарий, он не дает того же результата:

WixQuietExec:  Get-ItemProperty : Cannot find path 
WixQuietExec:  'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\v15\Setup' because it 
WixQuietExec:  does not exist.
WixQuietExec:  At C:\Program Files (x86)\TrustValidator Exchange Server Plugin\test.ps1:10 
WixQuietExec:  char:16
WixQuietExec:  +     $properties = Get-ItemProperty -Path Registry::$setup
WixQuietExec:  +                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WixQuietExec:      + CategoryInfo          : ObjectNotFound: (HKEY_LOCAL_MACH...erver\v15\Set 
WixQuietExec:     up:String) , ItemNotFoundException
WixQuietExec:      + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetIt 
WixQuietExec:     emPropertyCommand

Теперь, если мы увидим сообщение об ошибке, это как если бы он имел доступ к дереву до HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ExchangeServer\потому что мой скрипт будет искать и перечислять все версии, так v15 должен быть доступен до этого момента, однако, когда он пытается пойти глубже, чтобы получить ItemPropertyне может.

Это привело меня к мысли, что, возможно, я что-то упускаю при запуске PowerShell из установщика WiX...?

Вот что в моем файле wxs:

<SetProperty Id="InstallPlugin"
     Before ="InstallPlugin"
     Sequence="execute"
     Value ="&quot;powershell.exe&quot; -Command &quot;cd '[INSTALLFOLDER]'; &amp; '[#TestPS1]' ; exit $$($Error.Count)&quot;" />
<CustomAction Id="InstallPlugin" BinaryKey="WixCA" DllEntry="WixQuietExec" Execute="deferred" Return="ignore" Impersonate="no" />

Ниже приведен список элементов, которые я уже пробовал или дважды проверил:

  • Я пробовал разные комбинации -NoProfile, -ExecutionPolicy ByPass, -Version 2.0 и все равно ничего хорошего.
  • Я уже запускаю установщик как InstallPrivileges="elevated"
  • Я уже управляю CustomAction как Execute="deferred" а также Impersonate="no"
  • Я пробовал с AdminImage="yes"
  • Я пытался установить <Property Id="MSIUSEREALADMINDETECTION" Value="1" />

Любая другая подсказка будет оценена.:(

1 ответ

Боже мой...

Хорошо, наконец-то все заработало. На самом деле было несколько проблем, и решения этих проблем были на самом деле кусочками информации, которую я собираю по нескольким вопросам SO.

Напомним, вот что я пытался сделать:

  1. Запустите PowerShell из WiX, чтобы запустить мой скрипт установки.
  2. Мой скрипт поиска в реестре Windows (требуется 64 бита) для определения местоположения установленного сервера Exchange
  3. Мой сценарий загружает сценарий командной консоли Exchange (EMS) (требуется 64-разрядный И соответствующий пользователь) из места установки
  4. В рамках сеанса EMS мой сценарий запускает множество других сценариев для регистрации плагина Exchange.

Проблема 1)

Независимо от того, что я сделал, установщик WiX всегда запускает мой PowerShell в 32-битной, это независимо от настроек Platform="x64", Win64="yes", и даже WixQuietExec64, Я даже построил установщик в Visual Studio как x64 а все остальное как x64,

Решение состоит в том, чтобы напрямую ссылаться на sysnative PowerShell, это должно быть sysnative в SetProperty,

C:\Windows\sysnative\WindowsPowerShell\v1.0\powershell.exe

Я действительно пробовал это раньше, и думал, что это не работает, но основная причина была замаскирована проблемой 2 ниже.

Проблема 2)

Везде, где я читаю, говорят, что нужно бегать с Execute="deferred" Impersonate="No", Я считаю, что это действительно сработает в большинстве случаев, если вы не делаете ничего прикольного. Однако мне пришлось Impersonate, Я обнаружил, что установщик WiX будет запускать ваш ЦС с повышенными правами пользователя NT Authority/System, Это облажалось, потому что Exchange Management Shell скрипт, который я пытался найти, в основном использовал бы ваши учетные данные и пытался установить сеанс с Exchange Server... и, конечно, вы не можете подключиться как NT Authority/System!

Решение заключается в использовании Impersonate="yes" так что установщик WiX будет запускать ваш ЦС с повышенными правами и пользователем, в котором вы сейчас авторизованы. У меня всегда было впечатление, что вы должны использовать Impersonate="no" когда используешь Execute="deferred"... но ты не

Я отказался от устранения неполадок в течение нескольких дней, а затем вернулся к нему и получил его работать. Две наиболее полезные команды, которые помогли мне понять это, были на самом деле:

  • кто я
  • Get-ChildItem env: (чтобы проверить PROCESSOR_ARCHITECTURE)
Другие вопросы по тегам