Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как по Handle/ID процесса, получ.все его дескрипт. 
:(
    Опции темы
RUVATA
Дата 18.1.2011, 11:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 24.8.2010

Репутация: нет
Всего: нет



Всем доброго времени суток...
Честно уважаемые "дот.нетчики", пытаясь решить тривиальную задачу
количество седых волос на моей голове
вышло за пределы нуля и теперь неумолимыми темпами удваивается smile Java давался проще...
Суть...
Программе выполняющей определенные манипуляции с файлами, перед тем как их выполнять необходимо
убедиться что файл свободен и не занят иными приложениями, а в частности MS Excel, MS Office, 1С или Инфо-бухгалтер,
а так-же, что оказалось вообще "фетиш" занят ли он / открыт ли по сети, соответсвенно теми-же приложениями...
Это как бы минимум требований, а желаемо еще бы определить каким процессом если локально, или какой учеткой если по сети он юзается...
Ну и в идеале иметь определенный инструментарий, который вооружившись правами админа мог бы грубо эти ресурсы высвобождать.

1) Сперва попробовали въехать в то ка-же вообще определить используется ли известный файл вообще
думали здесь,  и на нескольких других форумах посвященным программированию в среде .NET
но ничего толкового не надумали, самопоиск и советы на вашем форуме свелись к  "танцам с бубном" вокруг  API NtQuerySystemInformation из ntdll.dll
вот здесь и здесь можно понять какой это "кровоточащий геморрой"
...
ну только если файл вообще процессом заблокирован Уровень внешнего доступа "None", то сам факт использования определяем обрабатывая исключение WinIOerror 
пытаясь получить исключительную привилегию на файл.
Код

 Try
        Dim test As FileStream = File.Open("F:\Test.txt", FileMode.Open, FileAccess.ReadWrite, FileShare.None)
        Catch ex As Exception
            If ex.TargetSite.Name = "WinIOError" Then MsgBox("файл занят другим приложением")
  End Try

...
Этого мало, как узнать каким ? 
Но вот казалось выход замячил... можно же юзать и стороннюю утилитку, н/п Unlocker(консольный) или Handle.exe от SysInternals
мануал которого гордо гласит, Detected all used handle's in the tagert dirrectory with there process, pid, memory... (ни хрена подобного!!!)
вот вам пример использования handle.exe
Код

    Public Function UseHandle(ByVal Arg As String) 'Arg - это аргумент для handle.exe а именно целевая директория... прога должна вернуть описание всех занятых в ней файло, кем, пиды и.т.д.
        Dim my_handle As New Process
        Dim myProcessStartInfo As New ProcessStartInfo(System.Windows.Forms.Application.StartupPath & "\Handle.exe")
        Dim HandleText As String
        myProcessStartInfo.UseShellExecute = False
        myProcessStartInfo.RedirectStandardOutput = True
        myProcessStartInfo.Arguments = Arg
        myProcessStartInfo.CreateNoWindow = True
        my_handle.StartInfo = myProcessStartInfo
        my_handle.Start()
        my_handle.WaitForExit()
        HandleText = my_handle.StandardOutput.ReadToEnd
        my_handle.Close()
        Return (HandleText) 
    End Function

Парсим HandleText, он метаморфозирует кому как нравится, я например класс-описатель соорудил для каждого (файл, процесс, пид)
Да только толку мало... работает если только файл юзается не системными процессами, т.е. явно локально запущенными программами не относящимися к сервисам и службам системы,
все файлы которые дрочит System и сеть ни хрена не беруться в расчет... 
Зато их охеренно чует 7-zip который нам черным по белому мессажит: "Файл занят другим процессом!", а ни Handle.exe ни приславутый Unlocker не чують на той-же директории подвоха.

Полное фиаско!
Ладно, что-то где-то проскакивало про WMI, я тогда еще не представлял какая брешь седины у меня образуется...
Кое как криком боком, научились юзать WMI, даже чуть въехали в структуру классов, базовые методы, как шаманить над коллекциями
вот мы уже можте вычленить список процессов, получить их Handle-Ы, и толку...
вот кстати пример
Код

Imports System
Imports System.Management
Imports System.IO
 
Class MyWMIQuery

        Public Shared Function Main(ByRef ProcessArray As String) As Integer

            Dim searcher As New ManagementObjectSearcher( _
                "root\CIMV2", _
                "SELECT * FROM Win32_Process")

            For Each queryObj As ManagementObject In searcher.Get()
                ProcessArray = ProcessArray & queryObj("Caption") & vbCrLf
            Next

        End Function

    End Class

не забыть установить у проекта ссылку на System.Management !!!
Imports не достаточно, по крайней мере для Visual Studio 2010
....
В многих местах упоминается что при помощи класcа "root\CIMV2" Win32_Directory
мы можем получить ту самую вымученную инфу о занятом файле...
но нигде не описано как, не говоря уж о примере кода... Лично я не догоняю так 
как свойств и методов пригодных для этого я у него не нашел, разве что свойство 
InUseCount но если я еще понимаю вражеский то:
The InUseCount property is an integer indicating the number of 'file opens' that are currently active against the file.
это лишь общее количество занятых файлов...
а как подобраться к их качеству?

Теперь я устремил свой взор в строну GDT(Global Discriptors Table) и LDT(Local Descriptors Table)

В итоге проблема до сих пор в подвешенном состоянии... несмотря на титанические усилия... но либо я 
не там копаю... либо это реально сложная задача!

Уважаемы знатоки ! smile Внимание вопрос, или даже несколько:
1)Зная Handle/ID или PID процесса, можно ли подобраться ко всем его ресурсам средствами vb.NET ... 
а именно к другим его дескрипторам описывающим занятые файлы, пробраться к его LDT ?

как говорит MSDN там тоже такую инфу можно найти!
2)Чем отличаются файлы занятые по сети от файлов занятыз локальными процессами, и почему гребанный архиватор
может определить что файл занят, а специальные утилиты нет ?

3) Что мне курить, колоть, или пить дальше ? smile







PM MAIL   Вверх
m0nax
Дата 30.1.2011, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 24.6.2010

Репутация: нет
Всего: нет



C помощью апишных функций можно получить список всех хендлов и PIDов
Из этого списка не сложно рассортировать какие хандлы в каких процессах

Сами хендлы можно получить с помощью NtQuerySystemInformation

Что бы определить файлы придется получать их имена по хендлам, прежде чем это делать придется узнать тип хендла и убедиться что хватает прав на общение с ним
значит нужен DuplicateHandle(для доступа)  и  NtQueryObject 


Само имя можно определить тем же NtQueryObject, там будут не совсем те имена которые мы привыкли видеть (\\systemroot или 1\\device  вместо С:\ и D:\)
чтоб получить в адекватном виде путь/имя нужно кой чего сделать, но это уже детали )

Вот собственно класс, который позволяет получить список файлов используемых процессом
конечно же на С# ибо вб знать не знаю
Код

    public class OpenedFileDetector
    {
        private static Dictionary<byte, string> typeHandles = new Dictionary<byte, string>();
        private static Dictionary<string, string> _fileNamePrefixes = new Dictionary<string, string>();

        public OpenedFileDetector()
        {
            RefreshFileNamePrefixes();
        }

        public FileInfo[] GetOpenedFiles(Process targetProcess)
        {
            Process currentProcess = Process.GetCurrentProcess();

            var files = new List<FileInfo>();
            SystemHandleEntry[] handles = GetAllHandles();

            foreach (SystemHandleEntry handleEntry in handles)
            {
                if (handleEntry.ProcessId < 0)
                    throw new Exception("Process Id < 0");

                if (handleEntry.GrantedAccess == 0x0012019F)
                    continue;

                if (handleEntry.ProcessId != targetProcess.Id)
                    continue;

                string type;
                if (typeHandles.ContainsKey(handleEntry.ObjectTypeNumber))
                    type = typeHandles[handleEntry.ObjectTypeNumber];
                else
                {
                    type = GetHandleType(handleEntry.Handle, currentProcess, targetProcess);
                    typeHandles.Add(handleEntry.ObjectTypeNumber, type);
                }

                if (String.Equals("File", type, StringComparison.InvariantCultureIgnoreCase))
                {
                    string devicePath = GetFileNameFromHandle(handleEntry.Handle, currentProcess, targetProcess);

                    if (!string.IsNullOrEmpty(devicePath))
                    {
                        string goodName = ConvertDevicePathToDosPath(devicePath, false);
                        files.Add(new FileInfo(goodName));
                    }
                }
            }
            currentProcess.Close();

            return files.ToArray();
        }

        public SystemHandleEntry[] GetAllHandles()
        {
            IntPtr ptr = IntPtr.Zero;
            int length = 65536;
            var handles = new SystemHandleInformation();
            NtStatus ret;
            do
            {
                try
                {
                    ptr = Marshal.AllocHGlobal(length);

                    int returnLength;
                    ret = NativeMethods.NtQuerySystemInformation(
                        SystemInformationClass.SystemHandleInformation, ptr, length, out returnLength);

                    if (ret == NtStatus.InfoLengthMismatch)
                    {
                        length = ((returnLength + 0xffff) & ~0xffff);
                    }
                    else if (ret == NtStatus.Success)
                    {
                        {
                            Type typeHandleEntry = typeof(SystemHandleEntry);

                            int handleCount = Marshal.ReadIntPtr(ptr).ToInt32();
                            int sizeStruct = Marshal.SizeOf(typeof(SystemHandleEntry));

                            handles.NumberOfHandles = handleCount;
                            handles.handles = new SystemHandleEntry[handleCount];

                            Int64 pointer = ptr.ToInt32() + IntPtr.Size;

                            for (int i = 0; i < handleCount; i++)
                            {
                                handles.handles[i] = (SystemHandleEntry)Marshal.PtrToStructure(
                                    new IntPtr(pointer + sizeStruct * i),
                                    typeHandleEntry);
                            }
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(ptr);
                }
            } while (ret == NtStatus.InfoLengthMismatch);

            return handles.handles;
        }

        private static void RefreshFileNamePrefixes()
        {
            const int MAX_PATH = 254;
            // Just create a new dictionary to avoid having to lock the existing one.
            var newPrefixes = new Dictionary<string, string>();
            for (char c = 'A'; c <= 'Z'; c++)
            {
                var lpTargetPath = new StringBuilder(MAX_PATH);

                if (NativeMethods.QueryDosDevice(c + ":", lpTargetPath, MAX_PATH) > 2)
                {
                    newPrefixes.Add(lpTargetPath.ToString(), c + ":");
                }
            }

            _fileNamePrefixes = newPrefixes;
        }

        public string GetFileNameFromHandle(IntPtr fileHandle, Process currProc, Process targetProc)
        {
            SafeObjectHandle safeFileHandle = null;

            try
            {
                bool duplOk = NativeMethods.DuplicateHandle(targetProc.Handle,
                                                            fileHandle, currProc.Handle, out safeFileHandle,
                                                            0, false, DuplicateHandleOptions.DUPLICATE_SAME_ACCESS);

                if (!duplOk || safeFileHandle == null)
                    return null;

                var nameInfo = NtQueryObject<ObjectNameInformation>(safeFileHandle.DangerousGetHandle(),
                                                                    ObjectInformationClass.ObjectNameInformation);

                return nameInfo.Name;
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
            finally
            {
                if (safeFileHandle != null)
                    safeFileHandle.Close();
            }
        }


        public string GetHandleType(IntPtr handle, Process currProc, Process targetProc)
        {
            SafeObjectHandle objectHandle = null;
            try
            {
                bool duplOk = NativeMethods.DuplicateHandle(targetProc.Handle,
                                                            handle, currProc.Handle, out objectHandle, 0,
                                                            false, DuplicateHandleOptions.DUPLICATE_SAME_ACCESS);
                if (duplOk)
                {
                    var typeInfo = NtQueryObject<ObjectTypeInformation>(
                        objectHandle.DangerousGetHandle(),
                        ObjectInformationClass.ObjectTypeInformation);

                    return typeInfo.TypeName;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                if (objectHandle != null)
                    objectHandle.Close();
            }

            return "UNKNOWN";
        }


        private static T NtQueryObject<T>(IntPtr objectHandle, ObjectInformationClass typeInfo)
        {
            int leght = 512;
            IntPtr handleInfoPtr = IntPtr.Zero;

            try
            {
                    handleInfoPtr = Marshal.AllocHGlobal(leght);

                NtStatus ret = NativeMethods.NtQueryObject(objectHandle, typeInfo, handleInfoPtr,
                                                           leght, out leght);

                if (ret == NtStatus.BufferOverflow || ret == NtStatus.InfoLengthMismatch)
                {
                    //                     RuntimeHelpers.PrepareConstrainedRegions();
                    //                     try
                    //                     {
                    //                     }
                    //                     finally
                    {
                        handleInfoPtr = Marshal.ReAllocHGlobal(handleInfoPtr, new IntPtr(leght));
                    }

                    ret = NativeMethods.NtQueryObject(objectHandle, typeInfo, handleInfoPtr,
                                                      leght, out leght);
                }

                if (ret < NtStatus.Error)
                {
                    return (T)Marshal.PtrToStructure(handleInfoPtr, typeof(T));
                }
            }
            finally
            {
                Marshal.FreeHGlobal(handleInfoPtr);
            }

            return default(T);
        }


        private static string ConvertDevicePathToDosPath(string fileName, bool canonicalize)
        {
            bool alreadyCanonicalized = false;

            // If the path starts with "\SystemRoot", we can replace it with C:\ (or whatever it is).
            if (fileName.StartsWith("\\systemroot", StringComparison.OrdinalIgnoreCase))
            {
                fileName =
                    Path.GetFullPath(string.Format("{0}\\..{1}", Environment.SystemDirectory, fileName.Substring(11)));
                alreadyCanonicalized = true;
            }
            // If the path starts with "\??\", we can remove it and we will have the path.
            else if (fileName.StartsWith("\\??\\"))
            {
                fileName = fileName.Substring(4);
            }

            // If the path still starts with a backslash, we probably need to 
            // resolve any native object name to a DOS drive letter.)
            if (fileName.StartsWith("\\"))
            {
                Dictionary<string, string> prefixes = _fileNamePrefixes;

                foreach (var pair in prefixes)
                {
                    if (fileName.StartsWith(pair.Key + "\\"))
                    {
                        fileName = pair.Value + "\\" + fileName.Substring(pair.Key.Length + 1);
                        break;
                    }

                    if (fileName == pair.Key)
                    {
                        fileName = pair.Value;
                        break;
                    }
                }
            }

            if (canonicalize && !alreadyCanonicalized)
                fileName = Path.GetFullPath(fileName);

            return fileName;
        }

        #region Nested type: SafeObjectHandle

        [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
        private sealed class SafeObjectHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            private SafeObjectHandle()
                : base(true)
            {
            }

            internal SafeObjectHandle(IntPtr preexistingHandle, bool ownsHandle)
                : base(ownsHandle)
            {
                SetHandle(preexistingHandle);
            }

            protected override bool ReleaseHandle()
            {
                return NativeMethods.CloseHandle(handle);
            }
        }

        #endregion

        #region enums

        #region Nested type: DuplicateHandleOptions

        private enum DuplicateHandleOptions
        {
            DUPLICATE_CLOSE_SOURCE = 0x1,
            DUPLICATE_SAME_ACCESS = 0x2
        }

        #endregion

        #region Nested type: NtStatus

        private enum NtStatus : uint
        {
            // Success
            Success = 0x00000000,

            // Warning
            Warning = 0x80000000,
            GuardPageViolation = 0x80000001,
            DatatypeMisalignment = 0x80000002,
            Breakpoint = 0x80000003,
            SingleStep = 0x80000004,
            BufferOverflow = 0x80000005,
            NoMoreFiles = 0x80000006,
            HandlesClosed = 0x8000000a,
            PartialCopy = 0x8000000d,
            DeviceBusy = 0x80000011,
            InvalidEaName = 0x80000013,
            EaListInconsistent = 0x80000014,
            NoMoreEntries = 0x8000001a,
            LongJump = 0x80000026,
            DllMightBeInsecure = 0x8000002b,

            // Error
            Error = 0xc0000000,
            Unsuccessful = 0xc0000001,
            NotImplemented = 0xc0000002,
            InvalidInfoClass = 0xc0000003,
            InfoLengthMismatch = 0xc0000004,
        }

        #endregion

        #region Nested type: ObjectInformationClass

        private enum ObjectInformationClass
        {
            ObjectBasicInformation = 0,
            ObjectNameInformation = 1,
            ObjectTypeInformation = 2,
            ObjectTypesInformation = 3,
            ObjectHandleFlagInformation = 4,
            ObjectSessionInformation = 5
        }

        #endregion

        #region Nested type: SystemInformationClass

        private enum SystemInformationClass
        {
            SystemBasicInformation = 0,
            SystemPerformanceInformation = 2,
            SystemTimeOfDayInformation = 3,
            SystemProcessInformation = 5,
            SystemProcessorPerformanceInformation = 8,
            SystemHandleInformation = 16,
            SystemInterruptInformation = 23,
            SystemExceptionInformation = 33,
            SystemRegistryQuotaInformation = 37,
            SystemLookasideInformation = 45
        }

        #endregion

        #endregion

        #region structs

        #region Nested type: ObjectNameInformation

        [StructLayout(LayoutKind.Sequential)]
        private struct ObjectNameInformation
        {
            private UnicodeString name;

            public string Name
            {
                get { return name.Text; }
            }
        }

        #endregion

        #region Nested type: ObjectTypeInformation

        [StructLayout(LayoutKind.Sequential)]
        private struct ObjectTypeInformation
        {
            private UnicodeString name;

            public string TypeName
            {
                get { return name.Text; }
            }

            public int TotalNumberOfObjects;
            public int TotalNumberOfHandles;
            public int TotalPagedPoolUsage;
            public int TotalNonPagedPoolUsage;
            public int TotalNamePoolUsage;
            public int TotalHandleTableUsage;
            public int HighWaterNumberOfObjects;
            public int HighWaterNumberOfHandles;
            public int HighWaterPagedPoolUsage;
            public int HighWaterNonPagedPoolUsage;
            public int HighWaterNamePoolUsage;
            public int HighWaterHandleTableUsage;
            public int InvalidAttributes;
            public int GenericRead;
            public int GenericWrite;
            public int GenericExecute;
            public int GenericAll;
            public int ValidAccess;
            public byte SecurityRequired;
            public byte MaintainHandleCount;
            public ushort MaintainTypeList;
            public uint PoolType;
            public int PagedPoolUsage;
            public int NonPagedPoolUsage;
        }

        #endregion

        #region Nested type: SystemHandleEntry

        [StructLayout(LayoutKind.Sequential)]
        public struct SystemHandleEntry
        {
            public int ProcessId;
            public byte ObjectTypeNumber;
            public byte Flags;
            private short handleValue;
            public IntPtr ObjectPointer;
            public int GrantedAccess;

            public IntPtr Handle
            {
                get { return new IntPtr(handleValue); }
            }
        }

        #endregion

        #region Nested type: SystemHandleInformation

        [StructLayout(LayoutKind.Sequential)]
        private struct SystemHandleInformation
        {
            public int NumberOfHandles;
            public SystemHandleEntry[] handles;
        }

        #endregion

        #region Nested type: UnicodeString

        [StructLayout(LayoutKind.Sequential)]
        private struct UnicodeString
        {
            public short Length;
            public short MaximumLength;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string Text;
        }

        #endregion

        #endregion

        #region nativeMethods

        private static class NativeMethods
        {
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool CloseHandle(
                [In] IntPtr hObject);

            [DllImport("ntdll.dll")]
            internal static extern NtStatus NtQuerySystemInformation(
                [In] SystemInformationClass SystemInformationClass,
                [In] IntPtr SystemInformation,
                [In] int SystemInformationLength,
                [Out] out int ReturnLength);

            [DllImport("ntdll.dll")]
            internal static extern NtStatus NtQueryObject(
                [In] IntPtr Handle,
                [In] ObjectInformationClass ObjectInformationClass,
                [In] IntPtr ObjectInformation,
                [In] int ObjectInformationLength,
                [Out] out int ReturnLength);

            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            internal static extern bool DuplicateHandle(
                [In] IntPtr hSourceProcessHandle,
                [In] IntPtr hSourceHandle,
                [In] IntPtr hTargetProcessHandle,
                [Out] out SafeObjectHandle lpTargetHandle,
                [In] int dwDesiredAccess,
                [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
                [In] DuplicateHandleOptions dwOptions);

            [DllImport("kernel32.dll", SetLastError = true)]
            internal static extern int QueryDosDevice(
                [In] string lpDeviceName,
                [Out] StringBuilder lpTargetPath,
                [In] int ucchMax);
        }

        #endregion
    }


если кто найдет какие корявости и исправит не забудьте поделиться, ибо я пользуюсь классом


Это сообщение отредактировал(а) m0nax - 30.1.2011, 14:03
PM MAIL   Вверх
RUVATA
Дата 31.1.2011, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 24.8.2010

Репутация: нет
Всего: нет



мать моя женьщина smile 
конечно можно и так... may be
а вообще-то вот 
http://forum.vingrad.ru/act-ST/f-404/t-320169.html
я там последним постом открыл тайну миру smile
PM MAIL   Вверх
svm1977
Дата 24.10.2011, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 24.10.2011

Репутация: нет
Всего: нет



m0nax,  а можно поподробнее о вашем классе, который позволяет получить список файлов используемых процессом.
Какие функции надо вызывать из кода? 
Пробовал этот класс, он рабочий, но создаёт незавершаемые потоки с утечками памяти, не могу побороть. Ваш класс похож, но реализация немного другая.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0811 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.