Utilisation de Visual Studio 2008 pour créer un fichier msi afin de déployer mon programme avec un projet d'installation. J'ai besoin de savoir comment faire fonctionner le msi avec l'exe qu'il vient d'installer. Une action personnalisée? Si oui, veuillez expliquer où et comment. Merci.Exécutez exe après l'installation de msi?
Répondre
Ceci est une question commune. Je ne le fais pas avec juste une action personnalisée. Le seul moyen que je connaisse est de modifier le .msi après qu'il a été généré. Je cours un script Javascript en tant qu'événement post-build pour faire exactement cela. Il insère une nouvelle boîte de dialogue dans l'assistant d'installation, avec une case à cocher indiquant "Lancer l'application Foo?". Et puis il y a une action personnalisée pour exécuter l'application, si la case est cochée.
Il apparaît comme le dernier écran de la séquence de l'assistant d'installation. Ressemble à ceci:
Voici le script que j'utilise pour modifier le MSI:
// EnableLaunchApplication.js <msi-file>
// Performs a post-build fixup of an msi to launch a specific file when the install has completed
// Configurable values
var checkboxChecked = true; // Is the checkbox on the finished dialog checked by default?
var checkboxText = "Launch [ProductName]"; // Text for the checkbox on the finished dialog
var filename = "WindowsApplication1.exe"; // The name of the executable to launch - change this to match the file you want to launch at the end of your setup
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1;
var msiViewModifyUpdate = 2;
var msiViewModifyAssign = 3;
var msiViewModifyReplace = 4;
var msiViewModifyDelete = 6;
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " file");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql;
var view;
var record;
try
{
var fileId = FindFileIdentifier(database, filename);
if (!fileId)
throw "Unable to find '" + filename + "' in File table";
WScript.Echo("Updating the Control table...");
// Modify the Control_Next of BannerBmp control to point to the new CheckBox
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.StringData(11) = "CheckboxLaunch";
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the new CheckBox control
sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '9', '201', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the ControlEvent table...");
// Modify the Order of the EndDialog event of the FinishedForm to 1
sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(6) = 1;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the Event to launch the application
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the CustomAction table...");
// Insert the custom action to launch the application when finished
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();
if (checkboxChecked)
{
WScript.Echo("Updating the Property table...");
// Set the default value of the CheckBox
sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')";
view = database.OpenView(sql);
view.Execute();
view.Close();
}
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
function FindFileIdentifier(database, fileName)
{
// First, try to find the exact file name
var sql = "SELECT `File` FROM `File` WHERE `FileName`='" + fileName + "'";
var view = database.OpenView(sql);
view.Execute();
var record = view.Fetch();
if (record)
{
var value = record.StringData(1);
view.Close();
return value;
}
view.Close();
// The file may be in SFN|LFN format. Look for a filename in this case next
sql = "SELECT `File`, `FileName` FROM `File`";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
while (record)
{
if (StringEndsWith(record.StringData(2), "|" + fileName))
{
var value = record.StringData(1);
view.Close();
return value;
}
record = view.Fetch();
}
view.Close();
}
function StringEndsWith(str, value)
{
if (str.length < value.length)
return false;
return (str.indexOf(value, str.length - value.length) != -1);
}
Je suis à l'origine de ce Aaron Stebner's blog, puis modifié.
Enregistrez ce fichier Javascript dans le répertoire du projet (le même répertoire que contient .vdproj), nommez-le ModifyMsiToEnableLaunchApplication.js
. Pour chaque projet d'installation unique, vous devez modifier ce script et y mettre le nom d'exe approprié. Et puis, vous devez définir l'événement après génération dans le projet d'installation d'être ceci:
cscript.exe "$(ProjectDir)ModifyMsiToEnableLaunchApplication.js" "$(BuiltOuputPath)"
Assurez-vous de taper le nom de la macro $(BuiltOuputPath)
correctement. Le mot Ouput
est mal orthographié par Microsoft, et Built
n'est pas orthographié Build
!
Que oughtta le faire.
Voir aussi: this modification qui n'inclut pas la case à cocher "run Foo.exe" sur UNINSTALL.
Oui .. J'écrirait une action personnalisée, et le coller à la fin de la table InstallExecutionSequence
Je ne vois pas InstallExecutionSequence table? Sous des actions personnalisées, je vois Installer, Commit, Rollback et désinstaller. L'action personnalisée pointe-t-elle sur la sortie du programme principal? – Shawn
La table InstallExecutionSequence est interne au MSI et n'est pas exposée via Visual Studio. Vous aurez besoin d'un éditeur MSI comme Orca pour l'éditer. La modification manuelle des fichiers MSI n'est pas une tâche triviale. –
Je suis d'accord: modifier les fichiers MSI à la main n'est pas facile. Ce n'est pas facile ou trivial d'utiliser Orca. Vous pouvez utiliser le script fourni ci-dessous pour automatiser la tâche. Rapide et facile, testé et éprouvé. – Cheeso
En ce qui concerne la 'PostBuildEvent' a échoué avec le code d'erreur '1' 'Erreur non spécifiée' d'erreur, changer le PostBuildEvent de
cscript.exe \"$(ProjectDir)ModifyMsiToEnableLaunchApplication.js\" \"$(BuiltOuputPath)\"
à
cscript.exe "$(ProjectDir)ModifyMsiToEnableLaunchApplication.js" "$(BuiltOuputPath)"
En ce qui concerne la case cachée bug vous pouvez modifier la ligne 54 du script pour devenir:
sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '9', '201', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";
Merci pour les mises à jour. – Cheeso
En ce qui concerne le « bug case caché » Je compris ce qui suit qui est pas expliquée par Cheeso de et les réponses de Muleskinner ci-dessus:
Le changement du script (fourni par Muleskinner) place la position Y de la case à 201 (Je suppose que le top Y pixel pour le contrôle).Si vous changez Y, disons, 151 (pour l'aligner verticalement), le bug "soudainement" apparaît. La raison en est qu'il y a un autre contrôle dans la table de contrôle du msi, à savoir le 'BodyText' (champ 'Dialog' = 'FinishedForm') dont le Y est mis à 63 et sa hauteur à 138. C'est 138 + 63 = 201. Par conséquent, si vous modifiez la valeur Y de la case à cocher, le contrôle 'BodyText' chevauche le contrôle nouvellement ajouté et c'est pourquoi l'utilisateur doit passer la souris dessus pour afficher la case à cocher. Si vous n'avez pas 'BodyText' ou si son nombre de caractères est assez petit, vous pouvez changer (en utilisant l'éditeur d'Orca msi comme je le fais, ou en modifiant le script ci-dessus) les Y et les Hauteurs de ces 2 contrôles afin de pouvoir une position Y différente pour la case à cocher nouvellement ajoutée. La même chose s'applique pour le contrôle: 'BodyTextRemove' dans lequel encore une fois nous devons modifier sa valeur de hauteur (qui apparaît lors de la désinstallation)
Espérons que cela aide tous les utilisateurs qui avaient la même question que moi sur ce "bug"
Néanmoins, le script fait un très bon travail!
Une autre question était de savoir comment rendre invisible la case à cocher pendant la procédure de désistement. Utilisation de l'éditeur Orca NOBO ajouté les éléments suivants 2 lignes dans la table ControlCondition du msi:
Ligne 1 (Lorsque le contrôle doit être affiché):
(Dialog) FinishedForm (Control) CheckboxLaunch (Action) afficher (condition) RETIRER = ""
Row 2 (Lorsque le contrôle doit être invisible):
(Dialog) FinishedForm (Control) CheckboxLaunch (action) Masquer (Condition) SUPPRIMER <> ""
P.S. J'utilise VS 2010, sur Windows 7 (x64), mais je crois que ceux-ci devraient aussi fonctionner avec les versions précédentes.
Donc nous devons éditer le msi pour que nous déplacions la case? – ViFer
OK !!! Voici le code (sans les 2 fonctions auxiliaires 'FindFileIdentifier' & 'StringEndsWith' à la fin - utilisez les originaux), ce qui nous donne la possibilité de changer les Y et les hauteurs des contrôles, ainsi que d'ajouter les conditions de visibilité du contrôle Checkbox (voir les 2 commentaires qui sont marqués entre « NOUVEAU - START » à 'NOUVEAU - FIN):
// EnableLaunchApplication.js
// Performs a post-build fixup of an msi to launch a specific file when the install has completed
// Configurable values
var checkboxChecked = true; // Is the checkbox on the finished dialog checked by default?
var checkboxText = "Launch [ProductName]?"; // Text for the checkbox on the finished dialog
var filename = "*.exe"; // The name of the executable to launch - change * to match the file name you want to launch at the end of your setup
// Constant values from Windows Installer
var msiOpenDatabaseModeTransact = 1;
var msiViewModifyInsert = 1
var msiViewModifyUpdate = 2
var msiViewModifyAssign = 3
var msiViewModifyReplace = 4
var msiViewModifyDelete = 6
if (WScript.Arguments.Length != 1)
{
WScript.StdErr.WriteLine(WScript.ScriptName + " file");
WScript.Quit(1);
}
var filespec = WScript.Arguments(0);
var installer = WScript.CreateObject("WindowsInstaller.Installer");
var database = installer.OpenDatabase(filespec, msiOpenDatabaseModeTransact);
var sql
var view
var record
try
{
var fileId = FindFileIdentifier(database, filename);
if (!fileId)
throw "Unable to find '" + filename + "' in File table";
WScript.Echo("Updating the Control table...");
// Modify the Control_Next of BannerBmp control to point to the new CheckBox
sql = "SELECT `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_`='FinishedForm' AND `Control`='BannerBmp'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.StringData(11) = "CheckboxLaunch";
view.Modify(msiViewModifyReplace, record);
view.Close();
// NEW - START
// Insert the new CheckBox control
// I changed the value for Y below from 201 to 191 in order to make the checkbox more obvious to the user's eye. In order to do so, and avoid the controls 'BodyText' & 'BodyTextRemove' in the same form to
// overlap the checkbox, I added yet 2 more sql statements that change the values of the heights for the 'BodyText' & 'BodyTextRemove' from 138 to 128. This way I can play around with the values without using
// the Orca msi editor.
var CheckBoxY = 191; //This was initially set to 201
var NewHeight = 128; //This was initially set to 138
sql = "INSERT INTO `Control` (`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help`) VALUES ('FinishedForm', 'CheckboxLaunch', 'CheckBox', '9', '" + CheckBoxY + "', '343', '12', '3', 'LAUNCHAPP', '{\\VSI_MS_Sans_Serif13.0_0_0}" + checkboxText + "', 'CloseButton', '|')";
view = database.OpenView(sql);
view.Execute();
view.Close();
sql = "Select `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_` = 'FinishedForm' AND `Control` = 'BodyText'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(7) = NewHeight;
view.Modify(msiViewModifyReplace, record);
view.Close();
sql = "Select `Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Property`, `Text`, `Control_Next`, `Help` FROM `Control` WHERE `Dialog_` = 'FinishedForm' AND `Control` = 'BodyTextRemove'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(7) = NewHeight;
view.Modify(msiViewModifyReplace, record);
view.Close();
// NEW - END
WScript.Echo("Updating the ControlEvent table...");
// Modify the Order of the EndDialog event of the FinishedForm to 1
sql = "SELECT `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering` FROM `ControlEvent` WHERE `Dialog_`='FinishedForm' AND `Event`='EndDialog'";
view = database.OpenView(sql);
view.Execute();
record = view.Fetch();
record.IntegerData(6) = 1;
view.Modify(msiViewModifyReplace, record);
view.Close();
// Insert the Event to launch the application
sql = "INSERT INTO `ControlEvent` (`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES ('FinishedForm', 'CloseButton', 'DoAction', 'VSDCA_Launch', 'LAUNCHAPP=1', '0')";
view = database.OpenView(sql);
view.Execute();
view.Close();
WScript.Echo("Updating the CustomAction table...");
// Insert the custom action to launch the application when finished
sql = "INSERT INTO `CustomAction` (`Action`, `Type`, `Source`, `Target`) VALUES ('VSDCA_Launch', '210', '" + fileId + "', '')";
view = database.OpenView(sql);
view.Execute();
view.Close();
if (checkboxChecked)
{
WScript.Echo("Updating the Property table...");
// Set the default value of the CheckBox
sql = "INSERT INTO `Property` (`Property`, `Value`) VALUES ('LAUNCHAPP', '1')";
view = database.OpenView(sql);
view.Execute();
view.Close();
}
// NEW - START
WScript.Echo("Updating the ControlCondition table...");
// Insert the conditions where the Launch Application Checkbox appears
sql = "INSERT INTO `ControlCondition` (`Dialog_`, `Control_`, `Action`, `Condition`) VALUES ('FinishedForm', 'CheckboxLaunch', 'Show', 'REMOVE=\"\"')";
view = database.OpenView(sql);
view.Execute();
view.Close();
sql = "INSERT INTO `ControlCondition` (`Dialog_`, `Control_`, `Action`, `Condition`) VALUES ('FinishedForm', 'CheckboxLaunch', 'Hide', 'REMOVE<>\"\"')";
view = database.OpenView(sql);
view.Execute();
view.Close();
//NEW - END
database.Commit();
}
catch(e)
{
WScript.StdErr.WriteLine(e);
WScript.Quit(1);
}
Cela a corrigé la case à cocher de l'application de lancement apparaissant après la suppression! –
Qu'est-ce que ça a fait exactement? C'est peut-être juste que je me lève trop tard, mais j'ai de la difficulté à analyser ce que vous avez écrit là-bas, @Fidelis. – Cheeso
Cela semble être une solution beaucoup plus simple: Visual Studio Installer > How To Launch App at End of Installer
La solution originale était requise pour VS2005 (et peut-être VS2008)? –
Apparemment, cette solution plus simple n'affiche pas l'option checkbox. –
dans ce problème de solution est la configuration sera coincé juste avant son achèvement ... presque à 98% point. et il se termine juste quand vous quittez l'application. – mhesabi
- 1. Exécutez .NET exe sous Linux
- 2. Exécuter chm après l'installation de msi?
- 3. Apparence MSI indésirable après l'installation
- 4. Distribuer l'application C++ en .exe ou .msi?
- 5. .NET Installer - Diff entre .exe et .msi
- 6. Exécutez exe à partir de la page Web?
- 7. Démarrez exe après l'installation de msi mais en utilisant les privilèges utilisateur actuels
- 8. Exécutez le fichier exe sur un autre ordinateur
- 9. Création msi à partir de différents fichiers exe et jar
- 10. Lancer le programme après l'installation de msi
- 11. Envelopper un EXE existant dans un MSI - des inconvénients?
- 12. Installshield après installation réussie, ne lance pas exe
- 13. Comment exécutez-vous un autre fichier .exe à partir de VB.NET en tant qu'autre utilisateur?
- 14. Exécuter un fichier .exe automatiquement après l'installation
- 15. DeleteFile d'un EXE immédiatement après Process.WaitForExit échoue
- 16. SmallestDotNet en tant que CustomAction après l'installation de MSI
- 17. Comment obtenir la signature de fichier, type de fichiers (* .exe, * .js, * .msi, * .ocx, * .sys, * .vbs)?
- 18. exécuter exe après exportation réussie de svn de TortoiseSVN
- 19. Arrêt de MSI du lancement d'un fichier EXE dans le contexte SYSTEM
- 20. erreur accès exe-bad après l'exécution de cette ligne
- 21. Exécutable n'est pas signé après installé via MSI
- 22. Publication d'une application (.exe)
- 23. Exécutez sqlcmd sans installer SQL Server
- 24. Exécutez Wordpress dans RAMDISK?
- 25. Exécutez Microsoft.Speech sur IIS?
- 26. Exécutez le moteur quickfix
- 27. Exécutez inkscape en PHP
- 28. jquery, exécutez le formulaire
- 29. Quelles sont les différences entre les installateurs MSI et EXE, et que dois-je choisir?
- 30. wix: exécution de msi externe avant le début de l'installation
Wow Cheeso ... joli script – Nestor
comme un peu de magie. Je ne sais pas si MS a ajouté la capacité dans le projet d'installation pour VS2010. Je pense que c'est aussi possible de le faire avec WiX, mais je n'ai jamais utilisé Wix, donc ça marche pour moi. – Cheeso
Si l'interface est cachée (msi étant poussé avec des commandes d'installation silencieuse) cela fonctionnera-t-il encore? – Shawn