I am facing the following problem scenario:
- build an MSI the normal way ex: MyTest.msi
- rename it, leaving the msi extension. ex: MyTest_V1.0.0.msi
- Test it, it works. install success.
- Again repeat process. this time rename to ex: MyTest_V2.0.0.msi
- Test it, and it fails with a 'network error', while the file is on a local disk.
"A network error occurred while attempting to read from the file MyTest_V1.0.0.msi"
What gives, can't we simply rename an MSI file? Is there some issue that prevents this?
Now i stuck in this. please guide.
Highest Regards,
Muhammad Mubashir.
When you rename a MSI file and do not want it to have issues with any installations using the original MSI file, I recommend that you change some summary information and properties IN the renamed file. I normally modify:
- The Package Code, a GUID, it needs a new GUID
- The ProductName Property needs a different name
- The ProductCode, another GUID, needs a new GUID
You can use Microsoft's Orca database editor to modify these properties, if you can find it.
Here is an article covering how to use the Orca database editor to edit Windows Installer files: https://support.microsoft.com/en-us/kb/255905
Here are some additional details: https://msdn.microsoft.com/en-us/library/windows/desktop/aa370557(v=vs.85).aspx
- Some systems (that have had an older version of the Windows SDK will have Orca at \Program Files (x86)\Microsoft SDKs\Windows\v7.0\Bin\Orca.msi
- 2010 or earlier Windows SDKs should have it.
There is no limit in renaming MSI files.
But there are other traps, for example with updating MSIs, and some of the even include renaming.
If you want to update an MSI file with a socalled "Small Update" or "Minor Upgrade", it is no good idea to rename the MSI file !
You write
•Test it, it works. install success.
•Again repeat process.
I read nothing if you have uninstalled the old MSI in between (that would be a solution) or what type of update you V2.0 MSI shall be.
If you are not aware of the MSI upgrade details, first inform about the update types, the two mentioned and additionally "Major Upgrades". The latter have a little bit less traps than the first two :-)
(Patch upgrades I would leave out until you are really experienced.)
You can do a number of things wrong with updates. Be sure to have someone on board who is really experienced with MSI, otherwise there will be trouble, sooner or later.
Generally, if you are looking for a problem like yours, put out a logfile. You will find the described error there but often more information around.
I found solution my self. This is just like tutorial for WebSite Installer Setup. **
Steps:
For WebSites setup you have to install webDeployemnt setup and then from VS Add WebDeployemnt Project and this webProject ADD as referrence in etup project.
example: Precomiled Web Putputs from WebDeploy Project.
Difference b/w WebSite and Web App.
Websites have morethan one assemblies and not have .sln file.
WebApp have .sln file so all assemblies merge in one.
1- Set Setup Properties:
- RemovePreviousVersion True.
- DetectNewerVersionInstalled False.
2- Using vbScript or c# code in postbuild event of Setup Project;
- Change Product Version of your MSI.
- Change Product Code of your MSI. New Guid 32 char.
- Set MaxVersion to your New Version. this is available in Upgrade table of MSI.
- Makesure UpgradeCode must be same in all cases. means beware Not change it.
below i post both VbScript PBE.vbs and C# code.
Help webLinks from here i got an idea to overcome my problem:
https://www.simple-talk.com/dotnet/visual-studio/updates-to-setup-projects/
PBE.vbs calling from PostbuildEvent of MSIProject. cscript //nologo "$(ProjectDir)PBE.vbs" "$(BuiltOuputPath)"
Dim pInstaller
Set pInstaller = CreateObject("WindowsInstaller.Installer")
Dim pDatabase
Set pDatabase = pInstaller.OpenDatabase(WScript.Arguments(0), 2)
Dim pView1
Set pView1 = pDatabase.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'")
pView1.Execute
Dim pRecord1
Set pRecord1 = pView1.Fetch
If (Not pRecord1 Is Nothing) Then
pRecord1.StringData(1) = "1.0.5"
Else
MsgBox "Error during ProductVersion."
End If
pView1.Modify 4, pRecord1
pView1.Close
'MsgBox "Product Version is: " + pRecord1.StringData(1)
Dim pView3
Set pView3 = pDatabase.OpenView("SELECT VersionMax FROM Upgrade")
pView3.Execute
Dim pRecord3
Set pRecord3 = pView3.Fetch
If (Not pRecord3 Is Nothing) Then
pRecord3.StringData(1) = pRecord1.StringData(1)
Else
MsgBox "Error during VersionMax."
End If
pView3.Modify 4, pRecord3
pView3.Close
MsgBox "VersionMax is: " + pRecord3.StringData(1)
Dim pView2
Set pView2 = pDatabase.OpenView("SELECT `Value` FROM `Property` WHERE `Property` = 'ProductCode'")
pView2.Execute
Dim pRecord2
Set pRecord2 = pView2.Fetch
If (Not pRecord2 Is Nothing) Then
pRecord2.StringData(1) = CreateGUID()
Else
MsgBox "Error during ProductCode."
End If
pView2.Modify 4, pRecord2
pView2.Close
'MsgBox "Product Code is: " + pRecord2.StringData(1)
pDatabase.Commit
Function CreateGUID
Dim TypeLib
Set TypeLib = CreateObject("Scriptlet.TypeLib")
CreateGUID = Left(TypeLib.Guid, 38)
End Function
C# Console App code to do Rename msi file.
First you have to Add referrence in New Console app. That's a .NET
wrapper generated by tlbimp.exe, wrapping the ActiveX component
c:\windows\system32\msi.dll. You can let the IDE make one for you
with Project + Add Reference, COM tab, select "Microsoft Windows
Installer Object Library".
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using WindowsInstaller;
using System.Diagnostics;
// cscript //nologo "$(ProjectDir)WiRunSql.vbs" "$(BuiltOuputPath)" "UPDATE `Property` SET `Property`.`Value`='4.0.0.1' WHERE `Property`='ProductVersion'"
// "SELECT `Property`.`ProductVersion` FROM `Property` WHERE `Property`.`Property` = 'ProductVersion'"
/*
* That's a .NET wrapper generated by tlbimp.exe, wrapping the ActiveX component c:\windows\system32\msi.dll.
* You can let the IDE make one for you with Project + Add Reference, COM tab,
* select "Microsoft Windows Installer Object Library".
*/
namespace RenameMSI
{
[System.Runtime.InteropServices.ComImport(), System.Runtime.InteropServices.Guid("000C1090-0000-0000-C000-000000000046")]
class Installer { }
class Program
{
static void Main(string[] args)
{
#region New code.
string msiFilePath = string.Empty;
if (args.Length == 0)
{
Console.WriteLine("Enter MSI file complete path:");
//msiFilePath = Console.ReadLine();
msiFilePath = @"D:\TEST Projects\TestWebsites\MsiSetupForAsp.netApp\TestWebApplicationSetup\Debug\TestWebApplicationSetup.msi";
}
else
{
Console.WriteLine("Argument Received args[0]: " + args[0]);
msiFilePath = args[0];
}
////Debugger.Launch();
StringBuilder sb = new StringBuilder();
string[] words = msiFilePath.Split('\\');
foreach (string word in words)
{
sb.Append(word + '\\');
if (word.Contains("Debug") || word.Contains("Release"))
{
break;
}
else
{
}
}
Program p = new Program();
string VersionMax = p.GetMsiVersionProperty(msiFilePath, "ProductVersion");
string productName = p.GetMsiVersionProperty(msiFilePath, "ProductName");
p.SetMsiProperty(msiFilePath, "ProductVersion", "mub.sni");
p.SetMsiProperty(msiFilePath, "ProductName", "mub.sni");
//p.setMaxVersion(msiFilePath, );
//p.RenameMSI(msiFilePath);
#endregion
#region old code.
//String inputFile = @"C:\\Install1.msi";
//// Get the type of the Windows Installer object
//Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
//// Create the Windows Installer object
//Installer installer = (Installer)Activator.CreateInstance(installerType);
//WindowsInstaller.Installer ins = (WindowsInstaller.Installer)new Installer();
//string MSIpath = @"";
//Database db = ins.OpenDatabase(MSIpath, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly); //// Open the MSI database in the input file
//// Open a view on the Property table for the Label property
//View vw = db.OpenView(@"SELECT * FROM Property WHERE Property = 'ProductVersion'"); // I'd like to pull from other tables besides Property as well
//vw.Execute(null); // Execute the view query
//Record record = vw.Fetch(); // Get the record from the view
////// Get the Label from the data
//string Label = record.get_StringData(2);
//String[] a = Label.Split('.');
//string MajorNumber = a[0];
//string MinorNumber = a[1];
//int RevisionNumber = 0;
//int.TryParse(a[a.Length - 1], out RevisionNumber);
//RevisionNumber++;
//Console.WriteLine("Before " + record.get_StringData(1) + ": " + record.get_StringData(2));
//record.set_StringData(a.Length - 1, String.Concat(MajorNumber, ".", MinorNumber, ".", RevisionNumber.ToString()));
//Console.WriteLine("After " + record.get_StringData(1) + ": " + record.get_StringData(2));
//while (record != null)
//{
// Console.WriteLine(record.get_StringData(1));
// record.set_StringData(1, RevisionNumber.ToString());
// record = vw.Fetch();
//}
//vw.Modify(MsiViewModify.msiViewModifyMerge, record);
//vw.Close();
//db.Commit();
#endregion
//Console.Read();
}
private void setMaxVersion()
{
}
private void RenameMSI(string msiFilePath)
{
StringBuilder sb = new StringBuilder();
string[] words = msiFilePath.Split('\\');
foreach (string word in words)
{
sb.Append(word + '\\');
if (word.Contains("Debug") || word.Contains("Release"))
{
break;
}
else
{
}
}
Program p = new Program();
string VersionMax = p.GetMsiVersionProperty(msiFilePath, "ProductVersion");
string productName = p.GetMsiVersionProperty(msiFilePath, "ProductName");
string newMSIpath = sb.ToString() + string.Format("{0}_{1}.msi", productName, VersionMax);
Console.WriteLine("Original MSI File Path: " + msiFilePath);
Console.WriteLine("New MSI File Path: " + newMSIpath);
System.IO.File.Move(msiFilePath, newMSIpath);
}
private string GetMsiVersionProperty(string msiFilePath, string property)
{
string retVal = string.Empty;
// Create an Installer instance
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)new Installer();
// Open the msi file for reading
// 0 - Read, 1 - Read/Write
Database db = installer.OpenDatabase(msiFilePath, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeReadOnly); //// Open the MSI database in the input file
// Fetch the requested property
string sql = String.Format("SELECT Value FROM Property WHERE Property='{0}'", property);
//string sql = "SELECT * FROM Upgrade"; // "SELECT VersionMax FROM Upgrade"
View view = db.OpenView(sql);
//View view = db.OpenView(@"SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'");
view.Execute(null);
// Read in the fetched record
Record record = view.Fetch();
if (record != null)
{
retVal = record.get_StringData(1);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(record);
}
view.Close();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(view);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(db);
return retVal;
}
private string SetMsiProperty(string msiFilePath, string property, string value)
{
string retVal = string.Empty;
// Create an Installer instance
WindowsInstaller.Installer installer = (WindowsInstaller.Installer)new Installer();
// Open the msi file for reading
// 0 - Read, 1 - Read/Write
Database db = installer.OpenDatabase(msiFilePath, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeTransact); //// Open the MSI database in the input file
// Fetch the requested property
string sql = String.Format("SELECT Value FROM Property WHERE Property='{0}'", property);
View view = db.OpenView(sql); //View vw = db.OpenView(@"SELECT `Value` FROM `Property` WHERE `Property` = 'ProductVersion'");
view.Execute(null);
// Read in the fetched record
Record record = view.Fetch();
if (record != null)
{
record.set_StringData(1, value);
}
view.Modify(MsiViewModify.msiViewModifyReplace, record);
view.Close();
db.Commit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(record);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(view);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(db);
return retVal;
}
static string GetMsiProperty(string msiFile, string property)
{
string retVal = string.Empty;
return retVal;
}
}
}