Eintrag aus der MSI-Regristrierung entfernen
Hin und wieder beschäftige ich mich mit Setups, Deployment und Installationen. Verschiedene Betriebssysteme haben dazu unterschiedliche Lösungen entwickelt. Im Linux gibt es eine Fülle verschiedener Systeme, z. B. Deb- und RPM-Packete sowie Portage. In Windows gibt es MSI. An sich sind solche Packete eine gute Sache, nur kann man sich auch an verschiedenen Stellen in den Fuß schießen. Besonders einfach geht das mit MSI.
Problem
Wenn ich MSI-Packete erstelle, nutze ich dazu Windows Installer XML - eines der wenigen Open Source Projekte von Microsoft. Den Installer lasse ich oft nur für bestimmte Windows-Versionen zu:
<Condition Message='!(loc.ConditionInvalidWindowsVersion)'>
VersionNT = 500 OR VersionNT = 501 OR VersionNT = 600
</Condition>
Diese „Launch Conditions“ haben schon mehrfach Probleme mit nicht unterstützten Windows-Versionen gar nicht erst auftauchen lassen und eine Liste mit den entsprechenden VersionNT-Werten gibt hier.
Beachtet man dabei aber nicht, dass die Windows-Upgrade-Funktion aus einem Windows Vista in Windows 7 machen kann, bekommt man evtl. Probleme. Natürlich werden dabei schon installierte Programme übernommen und will man eine Anwendung mit eben gezeigter MSI-Startbedingung entfernen stellt man fest, dass das nicht geht:
Lösung
Um überhaupt erstmal an eine Lösung denken zu können, muss die aktuelle Version erstmal weg. Da man über die Systemsteuerung leider keine Art „Zwang“ auf eine Deinstallatin ausüben kann, muss man die Komandozeile (viel mehr ist das Ding in Windows auch wirklich nicht) bemühen. Mit Visual Studio wird ein Programm namens „msizap“ installiert, das genau für unsere Zwecke da ist: Alle Spuren einer Installation zu entfernen.
Dazu öffnet man am besten die „Visual Studio Komandozeile“ (ein normales CMD-Fenster mit ein paar gesetzten Umgebungsvariablen mehr) und entfernt die Installation anhand des Product-Codes:
Wie bei vielen MS-Tools werden erhöhte Rechte benötigt und man sieht die Ausgaben nur, wenn man das Programm schon aus einer Admin-CMD ausgeführt hat...
Außerdem bietet es sich an die Launch-Conditions zu verändern. Die einfachste, aber nicht vorausschauende Lösung ist es, Windows 7 explizit zu unterstützen:
<Condition Message='!(loc.ConditionInvalidWindowsVersion)'>
VersionNT = 500 OR VersionNT = 501 OR VersionNT = 600 OR VersionNT = 601
</Condition>
Product-Code finden
Bei einigen von mir erstellten Setups ändert sich ständig der Product-Code. Das hat den Hintergrund, dass bei MSI kleine Updates (sog. Minor Upgrades) nicht sonderlich gut unterstützt sind und ich in vielen Fällen „Major Upgrades“ bei neueren Versionen der Anwendung verwende. Somit kann man aber nicht im WiX-Quellcode nachsehen. Glücklicherweise fand (nach ganz unten scrollen) ich ein kleines Stük C#-Quellcode der alle Informationen über die intallierten Anwendungen ausgibt:
namespace Tools
{
class Program
{
static void Main(string[] args)
{
ListMsiInfo();
System.Console.ReadKey();
}
/// <summary>
/// This method REQUIRES a referance to msi.dll in Windows\System32. (com interopt)
/// </summary>
private static void ListMsiInfo()
{
// List of all the attributes you can query for.
var attributes = new string[]
{
"HelpLink",
"HelpTelephone",
"InstallDate",
"InstallLocation",
"InstalledProductName",
"InstallSource",
"LocalPackage",
"ProductID",
"Publisher",
"PackageName",
"RegCompany",
"RegOwner",
"URLInfoAbout",
"URLUpdateInfo",
"VersionMinor",
"VersionMajor",
"VersionString",
"Transforms",
"Language",
"AssignmentType",
"PackageCode",
"PackageName",
"ProductIcon",
"ProductName",
"Version",
"InstanceType",
};
// Get a referance to the WindowsInstaller.Installer via com interopt.
WindowsInstaller.Installer winInstaller = null;
Type oType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
if (oType == null) return;
winInstaller = (WindowsInstaller.Installer) Activator.CreateInstance(oType);
if (winInstaller == null) return;
// Iterate through all the productIds of the installed apps.
foreach (string productId in winInstaller.Products)
{
// Write out the product code.
Console.WriteLine(productId);
// try to get and print each attribute
foreach (string attribute in attributes)
{
string aVal = winInstaller.get_ProductInfo(productId, attribute);
if (string.IsNullOrEmpty(aVal)) continue;
Console.WriteLine("{0}:{1}", attribute, aVal);
}
}
}
}
}
Um nicht den Eintrag in der „Konsole“ zu verpassen, muss man den Zeilenpuffer eben dieser in den Eigenschaften erhöhen.
Update: Obrigen code habe ich noch um ein paar Filter erweitert. Das Ergebnis ist auf GitHub zu finden. Dort gibts auch Binaries, zum direkten Ausführen.
Hin und wieder beschäftige ich mich mit Setups, Deployment und Installationen. Verschiedene Betriebssysteme haben dazu unterschiedliche Lösungen entwickelt. Im Linux gibt es eine Fülle verschiedener Systeme, z. B. Deb- und RPM-Packete sowie Portage. In Windows gibt es MSI. An sich sind solche Packete eine gute Sache, nur kann man sich auch an verschiedenen Stellen in den Fuß schießen. Besonders einfach geht das mit MSI.Problem
burberry sales dnSDQIRJ burberryoutlet-store-online.com
- Antwort
Submitted by burberryoutletclst1 (not verified) on Fri, 2012-09-21 23:13.