É possível desativar a ajuda do msiexec GUI?

6

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?

    
por snoweagle 24.02.2014 / 19:45

4 respostas

3

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 ...

    
por 24.02.2014 / 22:38
4

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 ...

    
por 25.02.2014 / 02:30
2

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.

Solução 1 : VBScripts e Automação COM

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

Solução 2 : DTF - Ferramentas de implantação - .NET

O DTF (Deployment Tools Foundation) é essencialmente um wrapper .NET para a API do Windows Installer - ele possui uma coleção tão poderosa de assemblies .NET para trabalhar diretamente com aspectos do Windows Installer, que eu quero adicioná-lo aqui para referência para aqueles que procuram uma solução com muito controle de implantação refinado para resolver seu problema de administração. Código muito simples dentro de um aplicativo C # fornece controle total do processo de instalação. Aqui está um mock-up:

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:

  • Microsoft.Deployment.Compression.dll - Estrutura para empacotamento e descompactação de arquivos.
  • Microsoft.Deployment.Compression.Cab.dll - Implementa o empacotamento e descompactação do arquivo de gabinete.
  • Microsoft.Deployment.Resources.dll - Classes para ler e gravar dados de recursos em arquivos executáveis.
  • Microsoft.Deployment.WindowsInstaller.dll - Biblioteca de classes completa para as APIs do Windows Installer.
  • Microsoft.Deployment.WindowsInstaller.Package.dll - Classes estendidas para trabalhar com a instalação do Windows Installer e os pacotes de patches.

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.

Solução 3: Funções do instalador do C ++

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ô".

    
por 16.05.2014 / 16:22
0

Já experimentou o parâmetro / qn? ele deve suprimir todos os prompts da interface do usuário.

link

    
por 24.02.2014 / 21:46