2011-06-14 13 views
6

का उत्पाद कोड प्राप्त करें मेरे पास एक सी # प्रोग्राम है जहां मुझे एक स्थापित एमएसआई का उत्पाद कोड प्राप्त करना है। मेरे पास इनपुट के रूप में केवल एमएसआई नाम है। क्या यह प्रोग्रामेटिक रूप से किया जा सकता है?स्थापित एमएसआई

+0

आप सॉफ्टवेयर के साथ एक मशीन पर रजिस्ट्री खोज करने के लिए Regedit स्थापित का उपयोग करते थे द्वारा खोज स्ट्रिंग के लिए बहुत उपयोगी है? –

+0

इसके बारे में पूर्ण स्रोत कोड के साथ कोई अंतिम समाधान? – Kiquenet

+0

** [डीटीएफ (परिनियोजन उपकरण फाउंडेशन)] (https://serverfault.com/questions/577969/is-it-possible-to-disable-msiexec-help-gui/596519#596519) ** का एक गुच्छा है वाईईएक्स डाउनलोड के साथ .NET कक्षाएं वितरित की गईं जो आपको किसी भी COM इंटरऑप या क्लंक के बिना एमएसआई फ़ाइलों तक पहुंचने और संशोधित करने का एक आसान तरीका प्रदान करेगी। कुछ और संदर्भ के लिए प्रदान किए गए लिंक में जानकारी देखें। ** [वाईएक्स डाउनलोड करें] (http://wixtoolset.org/) ** डीटीएफ घटकों को पकड़ने के लिए। –

उत्तर

4

इस कोड को मैं किसी भी एमएसआई के UninstallString प्राप्त करने के लिए प्रयोग किया जाता है।

private string GetUninstallString(string msiName) 
{ 
    Utility.WriteLog("Entered GetUninstallString(msiName) - Parameters: msiName = " + msiName); 
    string uninstallString = string.Empty; 
    try 
    { 
     string path = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products"; 

     RegistryKey key = Registry.LocalMachine.OpenSubKey(path); 

     foreach (string tempKeyName in key.GetSubKeyNames()) 
     { 
      RegistryKey tempKey = key.OpenSubKey(tempKeyName + "\\InstallProperties"); 
      if (tempKey != null) 
      { 
       if (string.Equals(Convert.ToString(tempKey.GetValue("DisplayName")), msiName, StringComparison.CurrentCultureIgnoreCase)) 
       { 
        uninstallString = Convert.ToString(tempKey.GetValue("UninstallString")); 
        uninstallString = uninstallString.Replace("/I", "/X"); 
        uninstallString = uninstallString.Replace("MsiExec.exe", "").Trim(); 
        uninstallString += " /quiet /qn"; 
        break; 
       } 
      } 
     } 

     return uninstallString; 
    } 
    catch (Exception ex) 
    { 
     throw new ApplicationException(ex.Message); 
    } 
} 

यह इस तरह एक परिणाम दे देंगे:

MsiExec.exe /I{6BB09011-69E1-472F-ACAD-FA0E7DA3E2CE} 

इस स्ट्रिंग से, आप ब्रेसिज़ {}, जो 6BB09011-69E1-472F-ACAD-FA0E7DA3E2CE हो जाएगा भीतर-स्ट्रिंग ले सकते हैं। मुझे उम्मीद है कि यह उत्पाद कोड हो सकता है।

+2

यदि आप 64 बिट मशीन पर इस कोड का उपयोग करते हैं तो यह असफल हो जाएगा और आपका एप्लिकेशन 32 बिट है, क्योंकि यह आपको सॉफ़्टवेयर में 'वाह 6432Node' पर रीडायरेक्ट करेगा। 'RegistryKey.OpenBaseKey (RegistryHive.LocalMachine, RegistryView.Registry64) का उपयोग करें। ओपनसबकी (पथ) 'इसके बजाए। – modiX

6

this question मदद के लिए उत्तर दें? वे उत्पाद का नाम प्राप्त करना चाहते हैं, लेकिन शायद यह उत्पाद कोड के लिए भी काम करता है?

संपादित
आप MSI ही फ़ाइल (के रूप में अन्य प्रश्न के ऊपर के लिंक द्वारा सुझाए गए) डेटाबेस का उपयोग करने की जरूरत नहीं है, तो आप अपने एमएसआई के नाम के लिए निम्न रजिस्ट्री पथ खोज करने के लिए कोशिश कर सकते हैं फ़ाइल:

HKEY_CLASSES_ROOT\Installer\Products\*\SourceList 

Products शाखा के तहत कई प्रविष्टियों रहे हैं। उनमें से प्रत्येक एक उत्पाद कुंजी है। प्रत्येक शाखा में SourceList नोड होना चाहिए, जो बदले में PackageName मान होना चाहिए। उस मान में एमएसआई फ़ाइल का नाम है।

तो मैं क्या होता है:

for each key in Products 
{ 
    open SourceList subkey 
    read PackageName value 
    if name equals my msi file name 
    { 
     return key-name formatted as GUID 
    } 
} 
+0

ठीक है: -1 क्योंकि ...? –

+0

हालांकि, मुख्य नाम वास्तव में उत्पाद कोड का एक scrambled संस्करण है। किसी उत्पादकोड से रजिस्ट्री कुंजी प्रारूप में जाने में सहायता के लिए यहां देखें (http://stackoverflow.com/questions/1881643/msi-product-code-from-product-id/1881818#1881818)। आपको कुंजी नाम को अवरुद्ध करने के लिए बस इसे उलटना होगा। –

1

यह कोड सीधे एक एमएसआई फ़ाइल से उत्पाद कोड प्राप्त करता है। तो यह फ़ाइल को स्थापित किए बिना कोड पढ़ने की अनुमति देता है।

class MsiHandle : SafeHandleMinusOneIsInvalid 
{ 
    public MsiHandle() 
     : base(true) 
    { } 

    protected override bool ReleaseHandle() 
    { 
     return NativeMethods.MsiCloseHandle(handle) == 0; 
    } 
} 

class NativeMethods 
{ 
    const string MsiDll = "Msi.dll"; 

    [DllImport(MsiDll, CharSet = CharSet.Unicode, ExactSpelling = true)] 
    public extern static uint MsiOpenPackageW(string szPackagePath, out MsiHandle product); 

    [DllImport(MsiDll, ExactSpelling=true)] 
    public extern static uint MsiCloseHandle(IntPtr hAny); 

    [DllImport(MsiDll, CharSet = CharSet.Unicode, ExactSpelling = true)] 
    static extern uint MsiGetProductPropertyW(MsiHandle hProduct, string szProperty, StringBuilder value, ref int length); 


    [DllImport(MsiDll, ExactSpelling = true)] 
    public static extern int MsiSetInternalUI(int value, IntPtr hwnd); 

    public static uint MsiGetProductProperty(MsiHandle hProduct, string szProperty, out string value) 
    { 
     StringBuilder sb = new StringBuilder(1024); 
     int length = sb.Capacity; 
     uint err; 
     value = null; 
     if(0 == (err = MsiGetProductPropertyW(hProduct, szProperty, sb, ref length))) 
     { 
      sb.Length = length; 
      value = sb.ToString(); 
      return 0; 
     } 

     return err; 
    } 
} 

static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    static int Main(string[] args) 
    { 
     string msiFile = args[0]; 

     NativeMethods.MsiSetInternalUI(2, IntPtr.Zero); // Hide all UI. Without this you get a MSI dialog 

     MsiHandle msi; 
     uint err; 
     if (0 != (err = NativeMethods.MsiOpenPackageW(args[0], out msi))) 
     { 
      Console.Error.WriteLine("Can't open MSI, error {0}", err); 
      return 1; 
     } 

     // Strings available in all MSIs 
     string productCode; 
     using (msi) 
     { 
      if (0 != NativeMethods.MsiGetProductProperty(msi, "ProductCode", out productCode)) 
       throw new InvalidOperationException("Can't obtain product code"); 

      Console.WriteLine(productCode); 
      return 0; 
     } 
    } 
} 
सबवर्सन में

पूर्ण उदाहरण पर http://ankhsvn.open.collab.net/svn/ankhsvn/trunk/src/tools/Ankh.Chocolatey/ उपयोग उपयोगकर्ता नाम 'अतिथि' और कोई पासवर्ड।

2

सशर्त क्वेरी स्ट्रिंग के साथ WMI का उपयोग करने के लिए सबसे तेज़ और आसान तरीका है।

public string GetProductCode(string productName) 
    { 
     string query = string.Format("select * from Win32_Product where Name='{0}'", productName); 
     using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query)) 
     { 
      foreach (ManagementObject product in searcher.Get()) 
       return product["IdentifyingNumber"].ToString(); 
     } 
     return null; 
    } 
+1

यह प्रक्रिया अच्छी बीटी है जो इसे बहुत समय लेती है –

0
private static bool GetUninstallString(string ProductName) 
{ 
    try 
    { 
     RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); 
     var key = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") ?? 
      localKey.OpenSubKey(
       @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"); 

     if (key == null) 
       return false; 

     return key.GetSubKeyNames() 
       .Select(keyName => key.OpenSubKey(keyName)) 
       .Select(subkey => subkey.GetValue("DisplayName") as string) 
       .Any(displayName => displayName != null && displayName.Contains(ProductName)); 
    } 
    catch 
    { 
     // Log message     
     return false; 
    } 
} 

यह PRODUCTNAME

संबंधित मुद्दे