Question Est-il possible de désactiver l'interface graphique d'aide de msiexec?


J'automatise la récupération et l'installation sans assistance de packages .msi spécifiés avec un script PowerShell, mais si la commande est invoquée avec des erreurs de syntaxe, msiexec attend indéfiniment qu'un clic OK s'affiche sur son aide malgré la présence de / quiet et / ou / passive .

Pour le moment, je l'invoque avec:

(start-process -FilePath "msiexec" -ArgumentList "/i <path_to_package> /quiet /passive" -PassThru -Wait).ExitCode

Existe-t-il un moyen de désactiver l'affichage de l'aide msiexec?


6
2018-02-24 18:45


origine


Pourquoi y aurait-il des erreurs de syntaxe? Vous appelez la même commande, s'agit-il d'un espace '' dans le nom de votre chemin? nous pouvons contourner cela. - MDMoore313
La chaîne -ArgumentList est en cours de remplissage en lisant une entrée d'un fichier csv dans un fichier de package donné. - snoweagle


Réponses:


Malheureusement, je pense que le seul moyen d'éviter l'affichage de l'aide est de ...

... ne faites aucune faute de frappe ou de syntaxe.

J'aimerais avoir une meilleure réponse pour vous, mais ...


3
2018-02-24 21:38



Vous pouvez éviter l'interface graphique en passant par l'API Windows Installer, comme expliqué dans ma réponse ci-dessous. - Stein Åsmul


Il n’existe aucun moyen de désactiver ce comportement pour un msiexec commande contenant une erreur de syntaxe. Vous pouvez envelopper la commande dans quelque chose comme ce qui suit. Il utilise .NET Automation pour rechercher la fenêtre "utilisation" et la gérer dans le 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

Cela aussi a des problèmes. Avec /quiet une boîte de dialogue de progression est toujours affichée pendant l'installation. Vous pouvez envisager d'utiliser /qn au lieu de tout cacher msiexec Éléments de l'interface utilisateur. De même, le fichier MSI peut déclencher d'autres erreurs, non gérées, qui suspendent l'infidélité d'exécution. Peut-être inclure une valeur de délai d'attente? Et qu'en est-il des processus externes lancés à partir de la table CustomAction? Désolé, je suis près de faire de la randonnée maintenant ...


4
2018-02-25 01:30



Je pense que tous ces problèmes d’interface graphique pourraient être évités en passant par l’API Windows Installer comme décrit dans la réponse ci-dessous. Comment exécutez-vous ce script? Via PowerShell? Je suis en phase de déploiement, juste entre le développement et l’administration du système, donc j’ai tendance à éviter les interfaces graphiques chaque fois que je le peux. - Stein Åsmul
@Glytzhkof Oui, ma réponse utilise Powershell, tout comme la question du PO. Votre réponse, +1 btw, est assez intelligente, je n'ai pas travaillé directement avec l'API. J'imagine que si le PO a besoin En utilisant Powershell, votre exemple en C # pourrait être réécrit en PS. - jscott
Je pense que oui. Malheureusement, j'ai tendance à utiliser C # ou VBScript et non pas PowerShell. Je suppose que VBScript est très obsolète. Je ne suis pas familier avec l'appel des dll .NET depuis PowerShell. - Stein Åsmul


Je voudrais juste éviter d'aller via msiexec.exe tout à fait. Ceci est possible en passant par le API Windows Installer en utilisant des scripts ou du code.

Vous pouvez utiliser l’automatisation COM à l’aide de VBScript / VBA / VB ou DTF, un wrapper .NET pour l’API de Windows Installer, plus facile à utiliser à partir de langages .NET tels que C #.

Vous pouvez même passer directement via C ++ aux appels d'API Win32 bruts, mais ce n'est qu'une perte de temps, car vous disposez des équivalents COM et .NET qui appellent l'API Win32 brute dans le cadre de leur fonctionnement.


Solution 1: VBScripts et COM Automation

Si l’utilisation de l’automatisation est une option, vous devriez pouvoir passer par le Automatisation COM Windows Installer et automatiser l'installation / désinstallation de cette façon. Voici un script VBScript que vous pouvez mettre dans un fichier et exécuter (mettez à jour le nom du chemin d'accès MSI évidemment):

Const msiUILevelEndDialog = 128

Set msi = CreateObject("WindowsInstaller.Installer")
msi.UILevel = msiUILevelEndDialog
msi.InstallProduct( "C:\msifile.msi")
Set msi = Nothing

Solution 2: DTF - Fondation des outils de déploiement - .NET

DTF (Deployment Tools Foundation) est essentiellement un wrapper .NET pour l’API de Windows Installer. Il contient une collection d’assemblées .NET aussi puissante pour fonctionner directement avec les aspects de Windows Installer. pour une solution avec beaucoup de contrôle de déploiement à grain fin pour résoudre leur problème d'administration. Un code très simple dans une application C # permet un contrôle total du processus d'installation. Voici une maquette approximative:

using Microsoft.Deployment.WindowsInstaller.Installer;

Installer.SetInternalUI(InstallUIOptions.Silent);
Installer.InstallProduct(msiFilename, "ACTION=INSTALL ALLUSERS=1");

Vous pouvez obtenir DTF via le Boîte à outils WIX - qui est une solution globale pour créer des fichiers MSI à partir de fichiers source XML. Vous trouverez une excellente documentation dans DTF.chm et DTFAPI.chm et les fichiers réels sont dans le dossier d'installation principal. Les deux derniers sont généralement ceux dont vous avez besoin:

  • Microsoft.Deployment.Compression.dll - Cadre pour l'archivage et le déballage des archives.
  • Microsoft.Deployment.Compression.Cab.dll - Implémente l’archivage et le déballage des archives du cabinet.
  • Microsoft.Deployment.Resources.dll - Classes pour lire et écrire des données de ressources dans des fichiers exécutables.
  • Microsoft.Deployment.WindowsInstaller.dll - Bibliothèque de classes complète pour les API Windows Installer.
  • Microsoft.Deployment.WindowsInstaller.Package.dll - Classes étendues pour travailler avec l'installation de Windows Installer et les packages de correctifs.

Il vous suffit de créer un projet C #, de référencer ces fichiers et de coder votre propre application de déploiement avec le contrôle souhaité. Je ne suis pas configuré avec les outils pour DTF pour le moment, mais voir cet échantillon pour une idée générale du fonctionnement d’un programme C #.


Solution 3: fonctions du programme d'installation C ++

Je viens de penser que j'ajouterais ceci: cela est en grande partie hors de propos pour les administrateurs système, mais il serait peut-être utile de mieux comprendre la technologie MSI. Outre l’automatisation COM, il existe également un API Win32 avec des fonctions accessibles à partir de C ++. Bien sûr, de bien meilleures performances (l’automatisation COM appelle évidemment ces fonctions Win32 sous le capot - COM n’est qu’une enveloppe au-dessus de ces "vraies" fonctions bien sûr).

Je n'ai pas d'échantillons C ++ disponibles pour cela pour l'instant, mais voici la documentation du SDK: Référence de l'installateur Windows. Et un lien direct vers la liste des fonctions réelles de l'installateur. Cette liste de fonctions devrait vous donner une idée rapide de l’utilisation de cette technologie.

METTRE À JOUR: J'ai ajouté un échantillon d'extrait C ++ dans cette réponse stackoverflow sur différentes façons de désinstaller un package MSI (section 14 au bas de la réponse).

Les administrateurs système n'utilisent pas cette option, contrairement aux outils commerciaux permettant d'accéder à la base de données MSI du système (stockée à quelques emplacements dans le registre et avec un dossier de cache sur le disque). %SystemRoot%\Installer - et quelques "dossiers de travail"). Par exemple, votre SCCM ou un système de déploiement similaire les utilisera "sous le capot".


2
2018-05-16 14:22





Avez-vous essayé le commutateur / qn? il devrait supprimer toutes les invites de l'interface utilisateur.

http://technet.microsoft.com/en-us/library/cc759262(v=ws.10).aspx#BKMK_SetUI


0
2018-02-24 20:46



Vous verrez toujours le dialogue "utilisation" avec /qn si vous faites une erreur de syntaxe dans votre ligne de commande. par exemple msiexec /i some.msi typo /qn - jscott
Vient de tester cela, et que savez-vous, vous avez raison. Qu'en est-il de construire un shell cscript dans VBScript, puis de l'exécuter à partir de là? - Couradical