private void AddKey(MsiRegistry mr) { Dictionary <string, string> keys = MsiRegistries; int root = mr.Root; if (root == -1) { root = 2; //for sql server, should be per machine, not per user. so just use 2. } if (root < 0 || root > 3) { Logger.LogWarning("root=" + root + " which is out of valid range," + "" + mr.Key); return;//don't check invalid values } string HK = RegHelper.rootMap[root]; string path = HK + "\\" + mr.Key; if (mr.Name == "-" && String.IsNullOrEmpty(mr.Value)) { } //First if it already exists, need to check whether name=* or not if (keys.ContainsKey(path)) { //If new one is *, then change existing one if (mr.Name == "*") { keys[path] = "*"; } return; } //otherwise //Check whether it has parent in it //If my name!="*" and there is parent there already, don't add it //If myname="*" and there is parent in it, add me. // if (mr.Name == "*") { //If there is parent, and parent also =*, don't add it. //If there is parent but parent !=*, add it //If there is no parent, add it. //If there is kid, delete kid int hasParent = 0; int parentNameIsStar = 0; List <string> kids = new List <string>(); foreach (KeyValuePair <string, string> kv in keys) { //check parent keys if (path.StartsWith(kv.Key)) { hasParent++; if (kv.Value == "*") { parentNameIsStar++; } } //check kid if (kv.Key.StartsWith(path)) { kids.Add(kv.Key); } } //No parent, add it. if (hasParent <= 0) { keys.Add(path, mr.Name); } //Has parent,but parent is not star else if (parentNameIsStar == 0) { keys.Add(path, mr.Name); } //delete keys, becuase i am with star, any kids should be deleted foreach (string s in kids) { keys.Remove(s); } } /* * else //Do nothing, don't add them * { * * //If there is parent, don't add it. * //If there is no parent, add it. * //If there is kid, if kid is star, don't delete it. otherwise delete it * int hasParent = 0; * int parentNameIsStar = 0; * Dictionary<string, string> kids = new Dictionary<string, string>(); * foreach (KeyValuePair<string, string> kv in keys) * { * //check parent keys * if (path.StartsWith(kv.Key)) * { * hasParent++; * if (kv.Value == "*") parentNameIsStar++; * } * * //check kid * if (kv.Key.StartsWith(path)) kids.Add(kv.Key, kv.Value); * * } * * //No parent, add it. * if (hasParent <= 0) keys.Add(path, mr.Name); * * * //delete keys if kid is not star * foreach (KeyValuePair<string, string> kv in kids) * { * if(kv.Value!="*") * keys.Remove(kv.Key); * } * * } */ }
public MsiPackage(string msiFile) { //Do we need to take care of upcase or lower case, say, SQL_TOOLS.msi or sql_tools.msi?? PackageName = Path.GetFileName(msiFile); FullPath = msiFile; try { //Note:have to use using to open the Qdatabase otherwise will get error 110 //if open a few msi/msp: // QDatabase not able to open file name in uppper case. so lower case to open it. using (var qData = new QDatabase(msiFile.ToLower(), DatabaseOpenMode.ReadOnly)) { if (msiFile.ToUpper().EndsWith(".MSI")) { foreach (var p in qData.Properties) { switch (p.Property) { case "ProductName": this.ProductName = p.Value; break; case "ProductVersion": this.ProductVersion = p.Value; break; case "ProductCode": this.ProductCode = p.Value; break; case "UpgradeCode": this.UpgradeCode = p.Value; break; case "PlatformId": this.Cpu = p.Value; break; case "ProductLanguage": this.ProductLanguage = p.Value; break; default:; break; } } //Now try to apply transform and get its product code list after transform TransformProductCodes = MSIHelper.GetTransformProductCode(FullPath); this.PackageCode = qData.SummaryInfo.RevisionNumber; //Now to read File list foreach (var f in qData.Files) { string[] names = f.FileName.Split('|'); if (names.Length > 1) { if (!string.IsNullOrEmpty(names[1]) && !Files.Contains(names[1])) { Files.Add(names[1]); } } else { if (!Files.Contains(f.FileName)) { Files.Add(f.FileName); } } } /* * * Use the following table to determine the ROOT registry value: * -1 * For Per-User Installs, the registry value is written under HKCU; Per-Machine is HKLM * 0 * HKEY_CLASSES_ROOT * 1 * HKEY_CURRENT_USER * 2 * HKEY_LOCAL_MACHINE * 3 * HKEY_USERS */ //Now read regitry keys /* * if is is "*" The key is to be created, if absent, when the component is installed. Additionally, the key is to be deleted, if present, with all of its values and subkeys, when the component is uninstalled. */ //only read those whose name is "*" which means the setup owns this key excusivlly //we cannot delete the key shared with others, say, setup add things under key created by others Dictionary <int, string> rootMap = new Dictionary <int, string>() { { 0, "HKEY_CLASSES_ROOT" }, { 1, "HKEY_CURRENT_USER" }, { 2, "HKEY_LOCAL_MACHINE" }, { 3, "HKEY_USERS" } }; //some msi doesn't have registry try { foreach (var r in qData.Registries) { MsiRegistry smr = new MsiRegistry(); smr.Root = (int)r.Root; smr.Key = r.Key; smr.Name = r.Name; smr.Value = r.Value; MsiRegistries.Add(smr); } }catch (Exception ex) { Logger.LogError("MsiPackage:qData.Registries:\n" + ex.Message); } } else { throw new InvalidDataException("[" + msiFile + "]The file doesn't have msi extension!"); } } } catch (Exception ex) { Logger.LogError("MsiPackage:" + ex.Message); failedPackage = true; return; } }