c# - повторное использование подключенных методов

173
16 января 2022, 13:40

Нужен способ вытаскивать инфу из msi пакета. Нашел решение в инете, на его основе сделал класс

internal class GetMsiInfo {
        #region using msi.dll
        [DllImport("msi.dll", SetLastError = true)]
        private static extern uint MsiOpenDatabase(string szDatabasePath, IntPtr phPersist, out IntPtr phDatabase);
        [DllImport("msi.dll", CharSet = CharSet.Unicode)]
        private static extern int MsiDatabaseOpenViewW(IntPtr hDatabase, [MarshalAs(UnmanagedType.LPWStr)] string szQuery, out IntPtr phView);
        [DllImport("msi.dll", CharSet = CharSet.Unicode)]
        private static extern int MsiViewExecute(IntPtr hView, IntPtr hRecord);
        [DllImport("msi.dll", CharSet = CharSet.Unicode)]
        private static extern uint MsiViewFetch(IntPtr hView, out IntPtr hRecord);
        [DllImport("msi.dll", CharSet = CharSet.Unicode)]
        private static extern int MsiRecordGetString(IntPtr hRecord, int iField, [Out] StringBuilder szValueBuf, ref int pcchValueBuf);
        [DllImport("msi.dll", ExactSpelling = true)]
        private static extern IntPtr MsiCreateRecord(uint cParams);
        [DllImport("msi.dll", ExactSpelling = true)]
        private static extern uint MsiCloseHandle(IntPtr hAny);
        [DllImport("msi.dll", CharSet = CharSet.Auto)]
        public static extern uint MsiDatabaseCommit(IntPtr phDatabas);
        #endregion
        public string ValueProperty { get; private set; }

        //public void GetMSIInfo(string fileName, string property) {
        public void GetMSIInfo(string fileName, string property)
        {
            try
            {
                using (Stream stream = new FileStream(fileName, FileMode.Open))
                {
                }
            }
            catch (Exception e)
            {
                //check here why it failed and ask user to retry if the file is in use.
                Console.WriteLine(e.Message);
            }
            var sqlStatement = "SELECT * FROM Property WHERE Property = '" + property + "'";
            var phDatabase = IntPtr.Zero;
            var phView = IntPtr.Zero;
            var hRecord = IntPtr.Zero;
            var szValueBuf = new StringBuilder();
            var pcchValueBuf = 255;
            // Open the MSI database in the input file
            var val = MsiOpenDatabase(fileName, IntPtr.Zero, out phDatabase);
            hRecord = MsiCreateRecord(1);
            // Open a view on the Property table for the version property
            var viewVal = MsiDatabaseOpenViewW(phDatabase, sqlStatement, out phView);
            // Execute the view query
            var exeVal = MsiViewExecute(phView, hRecord);
            // Get the record from the view
            var fetchVal = MsiViewFetch(phView, out hRecord);
            // Get the version from the data
            var retVal = MsiRecordGetString(hRecord, 2, szValueBuf, ref pcchValueBuf);
            uint uRetCode;
            uRetCode = MsiDatabaseCommit(phDatabase);
            uRetCode = MsiCloseHandle(phView);
            uRetCode = MsiCloseHandle(hRecord);
            uRetCode = MsiCloseHandle(phDatabase);
            ValueProperty = szValueBuf.ToString();
        }
    }

Только он отрабатывает нормально при первом вызове метода. При втором вылетает ошибка.

System.AccessViolationException
  HResult=0x80004003
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=Install-From-MSI
  StackTrace:
   at Install_From_MSI.GetMsiInfo.MsiRecordGetString(IntPtr hRecord, Int32 iField, StringBuilder szValueBuf, Int32& pcchValueBuf)
   at Install_From_MSI.GetMsiInfo.GetMSIInfo(String fileName, String property) in C:\Users\user\source\repos\\Install-From-MSI\GetMsiInfo.cs:line 78
   at Install_From_MSI.NewApp.<>c__DisplayClass39_0.<GetInfoMSI>b__0() in C:\Users\user\source\repos\\Install-From-MSI\NewApp.cs:line 102
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()   

Просьба подсказать в какую сторону копать. Спасибо.

READ ALSO
Task.FromException c#

Task.FromException c#

Создаю асинхронную задачу Task

143
Ошибка в unity CS1061

Ошибка в unity CS1061

Все работало буквально 10 минут назадСоздал новую сцену, все так же работало, но потом что-то пошло не так

179
Возвращение двух переменных из метода

Возвращение двух переменных из метода

Помогите самоваруЕсть два метода, которые по отдельности возвращают координаты х и у соотвественно

76