Вместо нижней строки
//header("Location:".ADMIN_URL."/index.php");
напишите
echo("<script>location.href = '".ADMIN_URL."/index.php?msg=$msg';</script>");
или
?><script><?php echo("location.href = '".ADMIN_URL."/index.php?msg=$msg';");?></script><?php
Это определенно решит вашу проблему. Я столкнулся с одной и той же проблемой, но решил решить эту проблему путем написания заголовка.
Вы правы насчет @{}
, это новая хеш-таблица. Я думаю, что для того, что вы хотите, вы можете просто создать список и каждый продукт, который проходит итерацию для сбора свойств, вы можете добавить его в этот список
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var Products = installerObj.Products;
List<Hashtable> ProductCollection = new List<Hashtable>();
foreach (var product in Products)
{
Hashtable hash = new Hashtable();
hash.Add("ProductCode", product);
string[] Attributes = { "Language", "ProductName", "PackageCode", "Transforms", "AssignmentType", "PackageName", "InstalledProductName", "VersionString", "RegCompany", "RegOwner", "ProductID", "ProductIcon", "InstallLocation", "InstallSource", "InstallDate", "Publisher", "LocalPackage", "HelpLink", "HelpTelephone", "URLInfoAbout", "URLUpdateInfo" };
foreach (var attribute in Attributes)
{
try
{
var details = installer.ProductInfo[product.ToString(), attribute.ToString()];
hash.Add(attribute, details);
}
catch
{
}
}
ProductCollection.Add(hash);
}
Теперь просто обратитесь к ProductCollection, чтобы получить сведения о вашем продукте. Если вы хотите пойти дальше, вы можете создать класс для каждого MSI и попросить ваш процесс создать объект для каждого продукта.
public class MSIInfo
{
public string ProductCode { get; set; }
public string Language { get; set; }
public string ProductName { get; set; }
public string PackageCode { get; set; }
public string Transforms { get; set; }
public string AssignmentType { get; set; }
public string PackageName { get; set; }
public string InstalledProductName { get; set; }
public string VersionString { get; set; }
public string RegCompany { get; set; }
public string RegOwner { get; set; }
public string ProductID { get; set; }
public string ProductIcon { get; set; }
public string InstallLocation { get; set; }
public string InstallSource { get; set; }
public string InstallDate { get; set; }
public string Publisher { get; set; }
public string LocalPackage { get; set; }
public string HelpLink { get; set; }
public string HelpTelephone { get; set; }
public string URLInfoAbout { get; set; }
public string URLUpdateInfo { get; set; }
public override string ToString()
{
return $"{ProductName} - {ProductCode}";
}
public static IEnumerable<MSIInfo> GetProducts()
{
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var Products = installerObj.Products;
List<MSIInfo> ProductCollection = new List<MSIInfo>();
foreach (var product in Products)
{
MSIInfo msi = new MSIInfo();
msi.ProductCode = product.ToString();
foreach (var property in msi.GetType()?.GetProperties())
{
try
{
if (property.Name != "ProductCode")
{
string val = installer.ProductInfo[product.ToString(), property.Name];
property.SetValue(msi, val);
}
}
catch (System.Runtime.InteropServices.COMException)
{
}
}
ProductCollection.Add(msi);
}
return ProductCollection;
}
}
Когда у вас есть этот класс, вы можете получить коллекцию из своего кода следующим образом
var Products = MSIInfo.GetProducts();