2013-07-09 18 views
3

我面臨着以下問題方案:不能重命名MSI事後

  • 建立一個MSI的正常方式例如:MyTest.msi
  • 將其重命名,使MSI擴展。例如:MyTest_V1.0.0.msi
  • 測試它,它的工作原理。安裝成功。
  • 再次重複過程。這次重新命名爲ex:MyTest_V2.0.0.msi
  • 測試它,並且它在文件位於本地磁盤上時出現「網絡錯誤」。

網絡出錯試圖從文件MyTest_V1.0.0.msi閱讀」

是什麼給了,我們不能簡單地重命名MSI文件?是否有一些問題阻止了這一點? 現在我堅持在這。請指導。

最高的問候, 穆罕默德Mubashir。

+0

如果msi已經安裝並且您再次安裝,安裝程序將訪問原始源代碼,請參閱此帖以瞭解詳情http://stackoverflow.com/questions/17464068/the-feature-you-are-trying-to-訪問從-MSI-上本地驅動/ 17470557?noredirect = 1個#comment25387971_17470557 – weberik

回答

0

我找到了我自己的解決方案。這就像WebSite安裝程序安裝教程。 **

步驟: 的網站設置,您必須安裝webDeployemnt設置,然後從VS添加WebDeployemnt項目,這webProject添加爲etup項目referrence。例如:來自WebDeploy項目的預先編制的Web Putputs。

不同之處網站和Web應用程序。 網站有一個以上的程序集,沒有.sln文件。 WebApp具有.sln文件,因此所有程序集都合併爲一個。

1集設置屬性:

  • RemovePreviousVersion真。
  • DetectNewerVersionInstalled False。

2-在安裝項目的postbuild事件中使用vbScript或c#代碼;

  • 更改您的MSI的產品版本。
  • 更改您的MSI的產品代碼。新Guid 32 char。
  • 將MaxVersion設置爲新版本。這在MSI的升級表中可用。
  • Makesure UpgradeCode在所有情況下都必須相同。意味着要小心不要改變它。

下面我發佈兩者VBSCRIPT PBE.vbs和C#代碼。從這裏

幫助網站鏈接我有一個想法,以克服我的問題: https://www.simple-talk.com/dotnet/visual-studio/updates-to-setup-projects/

PBE.vbs從MSIProject的PostbuildEvent調用。 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#控制檯應用程序代碼來完成重命名MSI文件。

首先,您必須在新控制檯應用程序中添加引用。這是一個由tlbimp.exe生成的.NET 包裝,封裝了ActiveX組件 c:\ windows \ system32 \ msi.dll。您可以讓IDE爲您製作一個 ,使用Project +添加引用,COM選項卡,選擇「Microsoft Windows 安裝程序對象庫」。

代碼:

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; 
     } 
    } 
} 
1

重命名MSI文件沒有限制。

但還有其他陷阱,例如更新MSIs,甚至包括重命名。 如果要使用所謂的「小更新」或「次升級」更新MSI文件,重命名MSI文件不是好主意!

你寫

•測試它,它的工作原理。安裝成功。 •再次重複處理。

如果您之前卸載了舊的MSI(這將是一個解決方案),或者您的V2.0 MSI應該是什麼類型的更新,我什麼也不讀。

如果您不知道MSI升級詳細信息,請首先通知有關更新類型,所提及的兩個以及另外的「重大升級」。後者比前兩個陷阱少一點:-) (補丁升級我會離開,直到你真的有經驗。) 你可以做一些更新的錯誤。一定要有真正有MSI經驗的人加入,否則遲早會出現問題。

一般來說,如果您正在尋找像您這樣的問題,請提供一個日誌文件。您會在那裏找到所描述的錯誤,但通常會提供更多信息。

2

在重命名MSI文件,並且不希望它與使用原始MSI文件中的任何設備的問題,我建議你更改一些概要信息和屬性重命名文件。我通常修改:

  • 包代碼,一個GUID,它需要一個新的GUID
  • 產品名稱屬性需要一個不同的名稱
  • 的產品代碼,另一個GUID,需要一個新的GUID

如果可以找到它,可以使用Microsoft的Orca數據庫編輯器來修改這些屬性。

這裏是涵蓋了如何使用Orca數據庫編輯器編輯Windows Installer文件的文章:https://support.microsoft.com/en-us/kb/255905

這裏有一些額外的細節:https://msdn.microsoft.com/en-us/library/windows/desktop/aa370557(v=vs.85).aspx

  • 一些系統(即有過的舊版本Windows SDK將在\ Program Files(x86)\ Microsoft SDKs \ Windows \ v7.0 \ Bin \ Orca.msi上擁有Orca
  • 2010或更早版本的Windows SDK應該具有此功能