Infelizmente, acho que a única maneira de evitar a exibição da ajuda é ...
... não comete erros de digitação / erros de sintaxe.
Eu gostaria de ter uma resposta melhor para você, mas ...
Estou automatizando a recuperação automática & instalação de pacotes .msi especificados com um script powershell, mas se o comando for chamado com erros de sintaxe, o msiexec aguardará indefinidamente por um clique OK na tela de ajuda, apesar da presença de / quiet e / ou / passive.
No momento, estou invocando:
(start-process -FilePath "msiexec" -ArgumentList "/i <path_to_package> /quiet /passive" -PassThru -Wait).ExitCode
Existe alguma maneira de desativar a exibição da ajuda msiexec?
Não há como desabilitar esse comportamento para um comando msiexec
contendo um erro de sintaxe. Você poderia envolver o comando em algo como o seguinte. Ele usa a Automação .NET para procurar a janela "uso" e lidar com isso no script.
Add-Type -AssemblyName UIAutomationClient
Add-Type -AssemblyName UIAutomationTypes
# Note the invalid argument '/badswitch'
$mse = Start-Process -FilePath 'msiexec' -ArgumentList "/i package.msi /badswitch /quiet /passive" -PassThru
# Let msiexec at least get off the ground
[void] $mse.WaitForInputIdle()
# Create an AutomationElement from $mse's handle
$mseAuto = [Windows.Automation.AutomationElement]::FromHandle($mse.MainWindowHandle)
# A PropertyCondition for findAll()
$pane = New-Object Windows.Automation.PropertyCondition -ArgumentList (
[Windows.Automation.AutomationElement]::ControlTypeProperty,
[Windows.Automation.ControlType]::Pane
)
# Search for a child $pane element.
$findResult = $mseAuto.FindFirst(
[System.Windows.Automation.TreeScope]::Children,
$pane
)
# If there's a pane element in $mseAuto, and it contains "usage" string, it's an msiexec syntax issue, so close $mse's window.
if ( $findResult.Current.Name -match 'msiexec /Option <Required Parameter>' ) {
[void] $mse.CloseMainWindow()
} else {
# You should put something more sane here to handle waiting for "good" installs to complete.
$mse.WaitForExit()
}
$mse.ExitCode
Isso também tem problemas. Com /quiet
, um diálogo de progresso ainda é exibido durante a instalação. Você pode considerar usar /qn
, em vez disso, ocultaria todos os elementos da interface do usuário msiexec
. Além disso, o MSI pode acionar outros erros, não tratados, o que pausaria a infidelidade de execução. Talvez inclua um valor de tempo limite? E quanto ao processo externo iniciado a partir da tabela CustomAction? Desculpe, estou perto de divagar agora ...
Eu apenas evitaria passar por msiexec.exe completamente. Isso é possível através da API do Windows Installer usando scripts ou código.
Você pode usar a automação COM usando VBScript / VBA / VB ou usar o DTF, que é um wrapper .NET para a API do Windows Installer mais fácil de se trabalhar com linguagens .NET, como C #.
Você pode até ir diretamente via C ++ para as chamadas de API do Win32, mas isso é perda de tempo, pois você tem os equivalentes COM e .NET que chamam a API bruta do Win32 como parte de sua operação.
Se usar a automação for uma opção, você poderá usar a automação do Windows Installer COM e automatizar a instalação / desinstalação dessa maneira. Aqui está um VBScript que você pode colocar em um arquivo e executar (atualize o nome do caminho MSI obviamente):
Const msiUILevelEndDialog = 128
Set msi = CreateObject("WindowsInstaller.Installer")
msi.UILevel = msiUILevelEndDialog
msi.InstallProduct( "C:\msifile.msi")
Set msi = Nothing
using Microsoft.Deployment.WindowsInstaller.Installer;
Installer.SetInternalUI(InstallUIOptions.Silent);
Installer.InstallProduct(msiFilename, "ACTION=INSTALL ALLUSERS=1");
Você pode obter o DTF por meio do WIX toolkit - que é uma solução geral para criar arquivos MSI a partir de Arquivos de origem XML. Você encontrará uma documentação excelente em DTF.chm e DTFAPI.chm e os arquivos reais estão na pasta de instalação principal. Os dois últimos são geralmente os que você precisa:
Basta criar um projeto em C #, fazer referência a esses arquivos e codificar seu próprio aplicativo de implantação com qualquer controle desejado e necessário. Não estou configurando as ferramentas do DTF no momento, mas veja este exemplo uma ideia geral de como um programa C # funcionaria.
Eu apenas imaginei adicionar isso - é irrelevante para os administradores de sistema, acredito, mas pode ajudar a entender melhor a tecnologia MSI. Além da automação COM, há também uma API do Win32 com funções acessíveis a partir do C ++ . Muito melhor desempenho do curso (a automação COM, obviamente, chama essas funções Win32 sob o capô - COM é apenas um invólucro no topo dessas funções "reais" é claro).
Eu não tenho nenhum exemplo de C ++ disponível para isso agora, mas aqui está a documentação do SDK: Referência do Windows Installer . E um link direto para a lista de funções reais do instalador . Esta lista de funções deve fornecer uma ideia rápida de como é usar essa tecnologia.
UPDATE : adicionei um exemplo de snippet C ++ em este stackoverflow responde de diferentes maneiras para desinstalar um pacote MSI (seção 14 na parte inferior da resposta).
Os administradores de sistema não usariam essa opção, mas ferramentas comerciais acessariam o banco de dados MSI do sistema (armazenado em alguns locais no registro e com uma pasta de cache no disco - %SystemRoot%\Installer
- e algumas "pastas de trabalho" "). Por exemplo, o seu SCCM ou sistema de implementação semelhante os usará "sob o capô".
Já experimentou o parâmetro / qn? ele deve suprimir todos os prompts da interface do usuário.