0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10

Узнать открыт-закрыт файл в другой программе, можно и по заголовку, как угодно

05.04.2019, 12:22. Показов 7971. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Давно не могу решить этот "ребус" под названием "Как узнать когда открыт и когда закрыт файл в другой программе. Есть простая программа написана мной в VS 2017, Visual C#, Приложение Windows Forms (.NET Framework), версия FrameWork 4.6. Приложение очень простое, работает только локально, кнопок нет, полный автомат. мониторит одну папку примерно 1 раз в 10 секунд, папка всегда пустая, но когда там появляются файл(фалы) она их обрабатывает самым простым способом, копирует в другое место + оригинал перемещает в еще одно другое место - все это замечательно и безотказно давно работает..., не суть... отвлекся... что мне нужно:

1. Программа увидела файл локально в своей директории которую мониторит, необходимо что бы ДО копирования и ДО перемещения этого файла на 100% точно убедиться (моей программе) что этот файл УЖЕ ТОЧНО на 100% закрыт в другой программе все локально на одном ПК. программа эта в которой этот файл открыт а потом (пользователь его в ручную ЗАКРЫВАЕТ) называется Sound Forge, файл формата .WAV хотя это не важно... далее перечислю как пытался решить эту задачу:

Нашел способ как узнать ТОЧНЫЙ заголовок TITLE СаундФорджа (далее СФ) - работает на 100% и я сначала обрадовался - все проблема решена (думал я) в заголовке в СФ пишется имя файла с расширением который там открыт - пока этот открытый файл развернут на макс. внутри окна СФ-а... имя и расширение файла добавляются к TITLE главного окна и я точно вижу это из своей программы этой одной строкой кода:

C#
1
IntPtr Enable_SF_FileOpen = FindWindow(null, "Sony Sound Forge 8.0 - [" + Path.GetFileName(of) + "]");
в квадратных скобках где Path.GetFileName думаю понятно что там идет возврат только имени файла - эта функция работает безотказно у меня с самого начала... и так же на 100% точно, когда он будет закрыт в СФ (из заголовка исчезнет имя файла)... так и есть, пока файл развернут на макс. внутри Форджа, но в СФ любой открытый файл можно свернуть (минимизировать) не полностью или полностью и в этот момент из заголовка ПРОПАДАЕТ ИМЯ файла и мой код что выше не работает, вернее думает что файл закрыли, на самом деле нет... пробовал другие разные варианты но не во всем смог разобраться... а вот есть еще код который я совсем не пробовал, потому как ТЯМЫ не хватает разобраться в нем, пытался пытался но так и запытал себя до того что не понимаю где и что и куда и как это...

Узнать дескриптор окна запускаемой программы - сообщение номер 6, чую что я шаге от решения своей проблемы - но не хватает мне тямы понять куда и какую часть кода вставить в свою программу что бы работало. Может найдутся смелчаки, что помогут, старому увы, уже не молодому человеку разобраться в коде или подсказать другой рабочий вариант решения моей проблемы ?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.04.2019, 12:22
Ответы с готовыми решениями:

Как узнать открыт ли файл Excel
Ребята здравствуйте! много чего просмотрел в инете так и ни чего конкретного для себя не нашел, подскажите Как узнать открыт(именно открыт...

Как узнать, открыт ли нужный файл
Как узнать, открыт ли нужный файл с помощью API-функций? В Excel, например, можно скрыть окно книги, в этом случае API-функция...

Как узнать открыт ли Word файл?
Добрый день! Проблема следующая: на диске лежит файл word, его могут открывать кто угодно. Если пользователь открывает файл, и потом не...

17
 Аватар для sau
2773 / 2073 / 386
Регистрация: 22.07.2011
Сообщений: 7,820
05.04.2019, 12:52
totewekotiara,
может просто узнать каким процессом занят файл ?
Кликните здесь для просмотра всего текста

https://pastebin.com/VuhVnRC1
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Text;
using System.Threading;
 
namespace FileLockInfo
{
    public class Win32Processes
    {
        /// <summary>
        /// Return a list of processes that hold on the given file.
        /// </summary>
        public static List<Process> GetProcessesLockingFile(string filePath)
        {
            var procs = new List<Process>();
 
            var processListSnapshot = Process.GetProcesses();
            foreach (var process in processListSnapshot)
            {
                if (process.Id <= 4) { continue; } // system processes
                var files = GetFilesLockedBy(process);
                if (files.Contains(filePath)) procs.Add(process);
            }
            return procs;
        }
 
        /// <summary>
        /// Return a list of file locks held by the process.
        /// </summary>
        public static List<string> GetFilesLockedBy(Process process)
        {
            var outp = new List<string>();
 
            ThreadStart ts = delegate
            {
                try
                {
                    outp = UnsafeGetFilesLockedBy(process);
                }
                catch { Ignore(); }
            };
 
            try
            {
                var t = new Thread(ts);
                t.IsBackground = true;
                t.Start();
                if (!t.Join(250))
                {
                    try
                    {
                        t.Interrupt();
                        t.Abort();
                    }
                    catch { Ignore(); }
                }
            }
            catch { Ignore(); }
 
            return outp;
        }
 
 
        #region Inner Workings
        private static void Ignore() { }
        private static List<string> UnsafeGetFilesLockedBy(Process process)
        {
            try
            {
                var handles = GetHandles(process);
                var files = new List<string>();
 
                foreach (var handle in handles)
                {
                    var file = GetFilePath(handle, process);
                    if (file != null) files.Add(file);
                }
 
                return files;
            }
            catch
            {
                return new List<string>();
            }
        }
 
        const int CNST_SYSTEM_HANDLE_INFORMATION = 16;
        private static string GetFilePath(Win32API.SYSTEM_HANDLE_INFORMATION systemHandleInformation, Process process)
        {
            var ipProcessHwnd = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id);
            var objBasic = new Win32API.OBJECT_BASIC_INFORMATION();
            var objObjectType = new Win32API.OBJECT_TYPE_INFORMATION();
            var objObjectName = new Win32API.OBJECT_NAME_INFORMATION();
            var strObjectName = "";
            var nLength = 0;
            IntPtr ipTemp, ipHandle;
 
            if (!Win32API.DuplicateHandle(ipProcessHwnd, systemHandleInformation.Handle, Win32API.GetCurrentProcess(), out ipHandle, 0, false, Win32API.DUPLICATE_SAME_ACCESS))
                return null;
 
            IntPtr ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
            Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectBasicInformation, ipBasic, Marshal.SizeOf(objBasic), ref nLength);
            objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
            Marshal.FreeHGlobal(ipBasic);
 
            IntPtr ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
            nLength = objBasic.TypeInformationLength;
            // this one never locks...
            while ((uint)(Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectTypeInformation, ipObjectType, nLength, ref nLength)) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
            {
                if (nLength == 0)
                {
                    Console.WriteLine("nLength returned at zero! ");
                    return null;
                }
                Marshal.FreeHGlobal(ipObjectType);
                ipObjectType = Marshal.AllocHGlobal(nLength);
            }
 
            objObjectType = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
            if (Is64Bits())
            {
                ipTemp = new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32);
            }
            else
            {
                ipTemp = objObjectType.Name.Buffer;
            }
 
            var strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
            Marshal.FreeHGlobal(ipObjectType);
            if (strObjectTypeName != "File")
                return null;
 
            nLength = objBasic.NameInformationLength;
 
            var ipObjectName = Marshal.AllocHGlobal(nLength);
 
            // ...this call sometimes hangs. Is a Windows error.
            while ((uint)(Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectNameInformation, ipObjectName, nLength, ref nLength)) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
            {
                Marshal.FreeHGlobal(ipObjectName);
                if (nLength == 0)
                {
                    Console.WriteLine("nLength returned at zero! " + strObjectTypeName);
                    return null;
                }
                ipObjectName = Marshal.AllocHGlobal(nLength);
            }
            objObjectName = (Win32API.OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(ipObjectName, objObjectName.GetType());
 
            if (Is64Bits())
            {
                ipTemp = new IntPtr(Convert.ToInt64(objObjectName.Name.Buffer.ToString(), 10) >> 32);
            }
            else
            {
                ipTemp = objObjectName.Name.Buffer;
            }
 
            if (ipTemp != IntPtr.Zero)
            {
 
                var baTemp = new byte[nLength];
                try
                {
                    Marshal.Copy(ipTemp, baTemp, 0, nLength);
 
                    strObjectName = Marshal.PtrToStringUni(Is64Bits() ? new IntPtr(ipTemp.ToInt64()) : new IntPtr(ipTemp.ToInt32()));
                }
                catch (AccessViolationException)
                {
                    return null;
                }
                finally
                {
                    Marshal.FreeHGlobal(ipObjectName);
                    Win32API.CloseHandle(ipHandle);
                }
            }
 
            string path = GetRegularFileNameFromDevice(strObjectName);
            try
            {
                return path;
            }
            catch
            {
                return null;
            }
        }
 
        private static string GetRegularFileNameFromDevice(string strRawName)
        {
            string strFileName = strRawName;
            foreach (string strDrivePath in Environment.GetLogicalDrives())
            {
                var sbTargetPath = new StringBuilder(Win32API.MAX_PATH);
                if (Win32API.QueryDosDevice(strDrivePath.Substring(0, 2), sbTargetPath, Win32API.MAX_PATH) == 0)
                {
                    return strRawName;
                }
                string strTargetPath = sbTargetPath.ToString();
                if (strFileName.StartsWith(strTargetPath))
                {
                    strFileName = strFileName.Replace(strTargetPath, strDrivePath.Substring(0, 2));
                    break;
                }
            }
            return strFileName;
        }
 
        private static IEnumerable<Win32API.SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
        {
            var nHandleInfoSize = 0x10000;
            var ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
            var nLength = 0;
            IntPtr ipHandle;
 
            while (Win32API.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer, nHandleInfoSize, ref nLength) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
            {
                nHandleInfoSize = nLength;
                Marshal.FreeHGlobal(ipHandlePointer);
                ipHandlePointer = Marshal.AllocHGlobal(nLength);
            }
 
            var baTemp = new byte[nLength];
            Marshal.Copy(ipHandlePointer, baTemp, 0, nLength);
 
            long lHandleCount;
            if (Is64Bits())
            {
                lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
            }
            else
            {
                lHandleCount = Marshal.ReadInt32(ipHandlePointer);
                ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
            }
 
            var lstHandles = new List<Win32API.SYSTEM_HANDLE_INFORMATION>();
 
            for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
            {
                var shHandle = new Win32API.SYSTEM_HANDLE_INFORMATION();
                if (Is64Bits())
                {
                    shHandle = (Win32API.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                    ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8);
                }
                else
                {
                    ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle));
                    shHandle = (Win32API.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                }
                if (shHandle.ProcessID != process.Id) continue;
                lstHandles.Add(shHandle);
            }
            return lstHandles;
        }
 
        private static bool Is64Bits()
        {
            return Marshal.SizeOf(typeof(IntPtr)) == 8;
        }
 
        internal class Win32API
        {
            [DllImport("ntdll.dll")]
            public static extern int NtQueryObject(IntPtr ObjectHandle, int
                ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength,
                ref int returnLength);
 
            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);
 
            [DllImport("ntdll.dll")]
            public static extern uint NtQuerySystemInformation(int
                SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength,
                ref int returnLength);
 
            [DllImport("kernel32.dll")]
            public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
            [DllImport("kernel32.dll")]
            public static extern int CloseHandle(IntPtr hObject);
            [DllImport("kernel32.dll", SetLastError = true)]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
               ushort hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
               uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
            [DllImport("kernel32.dll")]
            public static extern IntPtr GetCurrentProcess();
 
            public enum ObjectInformationClass
            {
                ObjectBasicInformation = 0,
                ObjectNameInformation = 1,
                ObjectTypeInformation = 2,
                ObjectAllTypesInformation = 3,
                ObjectHandleInformation = 4
            }
 
            [Flags]
            public enum ProcessAccessFlags : uint
            {
                All = 0x001F0FFF,
                Terminate = 0x00000001,
                CreateThread = 0x00000002,
                VMOperation = 0x00000008,
                VMRead = 0x00000010,
                VMWrite = 0x00000020,
                DupHandle = 0x00000040,
                SetInformation = 0x00000200,
                QueryInformation = 0x00000400,
                Synchronize = 0x00100000
            }
 
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_BASIC_INFORMATION
            { // Information Class 0
                public int Attributes;
                public int GrantedAccess;
                public int HandleCount;
                public int PointerCount;
                public int PagedPoolUsage;
                public int NonPagedPoolUsage;
                public int Reserved1;
                public int Reserved2;
                public int Reserved3;
                public int NameInformationLength;
                public int TypeInformationLength;
                public int SecurityDescriptorLength;
                public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
            }
 
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_TYPE_INFORMATION
            { // Information Class 2
                public UNICODE_STRING Name;
                public int ObjectCount;
                public int HandleCount;
                public int Reserved1;
                public int Reserved2;
                public int Reserved3;
                public int Reserved4;
                public int PeakObjectCount;
                public int PeakHandleCount;
                public int Reserved5;
                public int Reserved6;
                public int Reserved7;
                public int Reserved8;
                public int InvalidAttributes;
                public GENERIC_MAPPING GenericMapping;
                public int ValidAccess;
                public byte Unknown;
                public byte MaintainHandleDatabase;
                public int PoolType;
                public int PagedPoolUsage;
                public int NonPagedPoolUsage;
            }
 
            [StructLayout(LayoutKind.Sequential)]
            public struct OBJECT_NAME_INFORMATION
            { // Information Class 1
                public UNICODE_STRING Name;
            }
 
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct UNICODE_STRING
            {
                public ushort Length;
                public ushort MaximumLength;
                public IntPtr Buffer;
            }
 
            [StructLayout(LayoutKind.Sequential)]
            public struct GENERIC_MAPPING
            {
                public int GenericRead;
                public int GenericWrite;
                public int GenericExecute;
                public int GenericAll;
            }
 
            [StructLayout(LayoutKind.Sequential, Pack = 1)]
            public struct SYSTEM_HANDLE_INFORMATION
            { // Information Class 16
                public int ProcessID;
                public byte ObjectTypeNumber;
                public byte Flags; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                public ushort Handle;
                public int Object_Pointer;
                public UInt32 GrantedAccess;
            }
 
            public const int MAX_PATH = 260;
            public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
            public const int DUPLICATE_SAME_ACCESS = 0x2;
            public const uint FILE_SEQUENTIAL_ONLY = 0x00000004;
        }
        #endregion
    }
}
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
06.04.2019, 03:34  [ТС]
Только в одной единственной программе этот файл может быть открыт, должен быть способ чуть полегче не в 400 строк програмного кода, у меня вся программа со всей своей логикой занимает меньше... Неужели все так сложно, я к тому что например что бы выяснить текст заголовка главного окна программы мне понадобилась лишь ОДНА строка кода, вот эта для примера:

C#
1
label1.Text = "Точный заголовок Forge80.exe = " + Process.GetProcessesByName("Forge80")[0].MainWindowTitle;
Всего одна строка и я вижу заголовок который меняется если файл открытый в нем развернут внутри Форджа... вот другой пример, опять одна строка:

C#
1
label3.Text = Process.GetProcessesByName("Forge80").Any() ? "процесс Forge80 Существует" : "процесс Forge80 НЕ СУЩЕСТВУЕТ!...";
а вот так я могу узнать запущен ли вообще Саунд Фордж, и опять КОД на 100% рабочий, этих двух строк было бы на 100% достаточно для решения моей проблемы если бы не один маленький нюанс... я к тому что мне очень трудно поверить в тот факт что нет более компактного способа, ну пуская не ОДНОЙ СТРОКОЙ КОДА как я показал выше пусть будет 15-20 строк кода но не 400 же... у меня вся программа меньше строк имеет... неужели в таком мощном и невероятно гибком языке программирования нет способа попроще? или вот последний пример:

C#
1
2
 [DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
эти две строки помещаем на уровне внутри формы, а следующие две внутри кнопки:

C#
1
2
IntPtr topWindow = FindWindow(null, "Sony Sound Forge 8.0 - [Sound.wav]"); // Пример поиска дескриптора окна
int test = topWindow.ToInt32(); // преобразуем переменную типа IntPtr в int
и только то, и эти 4 строки так же отлично работают на главном заголовке нужного мне окна, но только до того момента пока файл развернут на максимум внутри Форджа... Я почти уверен что существует способ в несколько строк кода для решения моей проблемы, поймите правильно я не пытаюсь кого то обидеть, я хочу найти ПОНЯТНЫЙ и простой способ как в тех ТРЁХ примерах что я показал выше, ну не могу я поверить что в СИ Шарп нет понятного и простого способа решения по сути простейшей проблемы... вспомнил, что еще пробовал Try Catch обработать ошибку IOExeption - программа перестала вылетать, стала устойчивой на 100% к этой ошибке и все такое, но есть одна ложка дегтя которая напрочь перечеркнула этот способ, при каждой возникшей ошибке ВСЕГДА вылетает окно обработки ошибок от .NET с предложением Продолжить или Выйти, если нажать продолжить программа исправно работает, может есть способ как убрать это окно на совсем? отключить его? что бы не было его ибо ошибку я сам обрабатываю а это окно только с толку сбивает лишний раз и мешает работать логике дальше, каждый раз приходиться нажимать Продолжить, да еще рядом есть кнопка Прервать - она лишь с толку сбивает других пользователей...

п.с. - и самое последние, допустим эти 400 строк мне помогут, но что мне с ними делать? какую часть использовать? пытался понять в каких переменных из этих 400 строк будет находиться нужный мне ответ но так и не понял, слишком много переменных во всех этих функциях - и нет четкого понимания в какой из них окажется ответ, ведь мне нужно будет его использовать в блоке if что бы принять дальнейшее логическое решение, а для этого надо понять в какой переменной будет находиться нужный мне ответ...
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
06.04.2019, 04:37
Цитата Сообщение от totewekotiara Посмотреть сообщение
пробовал Try Catch обработать ошибку IOExeption - программа перестала вылетать, стала устойчивой на 100% к этой ошибке и все такое, но есть одна ложка дегтя которая напрочь перечеркнула этот способ, при каждой возникшей ошибке ВСЕГДА вылетает окно обработки ошибок от .NET с предложением Продолжить или Выйти, если нажать продолжить программа исправно работает, может есть способ как убрать это окно на совсем? отключить его? что бы не было его ибо ошибку я сам обрабатываю а это окно только с толку сбивает лишний раз и мешает работать логике дальше, каждый раз приходиться нажимать Продолжить, да еще рядом есть кнопка Прервать - она лишь с толку сбивает других пользователей...
Значит неправильно обрабатываете или не везде. Если try/catch ловит исключение, никакого окна не появляется.
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
06.04.2019, 07:53  [ТС]
Цитата Сообщение от Someone007 Посмотреть сообщение
Значит неправильно обрабатываете или не везде. Если try/catch ловит исключение, никакого окна не появляется.
try/catch - отлично работает до тех пор, пока SForge является активным и не минимизированным... НО! стоит только свернуть фордж с открытым файлом... ну вообщем вы поняли...

если коротко, такой вот вариант try-catch я использовал:

C#
1
2
3
4
5
6
7
8
                try
                {
                    File.Move(of, LocalFiName);
                }
                catch (Exception ex)
                {
                    label3.Text = "Ошибка: " + ex.Message;
                }
есть идеи как исправить ТРУ-КАТЧ таким образом что бы и при потере курсора все еще не было попытки выполнить File.Move... ???
0
 Аватар для sau
2773 / 2073 / 386
Регистрация: 22.07.2011
Сообщений: 7,820
06.04.2019, 12:28
Цитата Сообщение от totewekotiara Посмотреть сообщение
и только то, и эти 4 строки так же отлично работают на главном заголовке нужного мне окна, но только до того момента пока файл развернут на максимум внутри Форджа...
или до того момента , пока не появится новая версия программы , где ваш FindWindows отвалится , слишком хрупкое решение. Кроме того , возможны сценарии , когда окно Вы не найдете , а файл все еще будет занят приложением - Вы будете все их учитывать ?

Касательно 400 строк , из открытого интерфейса там только одна функция - GetProcessesLockingFile ,
т.е Вам всего лишь нужно оформить этот код в файле cs (или в dll , если смущает лишний код в основном проекте) ,
с функционалом приватных функциий разбираться не обязательно.

GetProcessesLockingFile - возвращает список процессов блокирующих работу с файлом , в вашем случае достаточно убедится , что список пустой , после чего с файлом можно работать.

Цитата Сообщение от totewekotiara Посмотреть сообщение
при потере курсора все еще не было попытки выполнить File.Move... ???
не сможете переместить файл , пока с ним работает другое приложение .
- можно его скопировать в нужное вам место для дальнейшей обработки в вашем приложении , а основной файл удалить после того , как его отпустят.
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
06.04.2019, 18:10  [ТС]
Цитата Сообщение от sau Посмотреть сообщение
Сообщение от totewekotiara
при потере курсора все еще не было попытки выполнить File.Move... ???
не сможете переместить файл , пока с ним работает другое приложение .
- можно его скопировать в нужное вам место для дальнейшей обработки в вашем приложении , а основной файл удалить после того , как его отпустят.
файл и так копируется перед перемещением... что бы не гадать и т.д. приведу кусок кода из своей программы, в данный момент он выглядит так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int test_SF_Open = FindWindow(null, "Sony Sound Forge 8.0 - [" + Path.GetFileName(of) + "]").ToInt32();
 
                if (test_SF_Open == 0 || Process.GetProcessesByName("Forge80").Any() == false)
                {
                    try
                    {
                        File.Copy(of, NetFiName, false);
                        File.Move(of, LocalFiName);
                    }
                    catch (Exception ex)
                    {
                        // label3.Text = "Ошибка: " + ex.Message;
                        notifyIcon.BalloonTipText = "Ошибка File.Move: " + NetFiName + ex.Message + "...закройте файл!!!"; notifyIcon.ShowBalloonTip(1000);
                    }
                }
                else
                {
                    if (test_SF_Open != 0) // когда файл ТОЧНО 100% все еще открыт в Фордже...
                    {
                        notifyIcon.BalloonTipText = "Файл: " + NetFiName + " ...все еще открыт в Фордже, закройте файл!!!"; notifyIcon.ShowBalloonTip(1000);
                        // MessageBox.Show("Файл: " + Path.GetFileName(of) + " ...все еще открыт в Sound Forge, Закройте файл!!!");
                    }
                    
                    // сюда мы попадем если файл ВЕРОЯТНЕЕ всего еще открыт в Фордже, но не ФАКТ!...
 
                }
только прошу не ржите, код я все время меняю, дорабатываю, целью сделать все красиво не стоит, главное функциональность, это не вся логика определения что делать с ОДНИМ файлом в конкретный момент времени но самая главная... попробую кратко объяснить суть "Как работает пользователь с этим файлом":

Происходит запись звука, ОДНА запись, ОДНОГО файла, локально в одной программе, после запись останавливается, обрабатывается все в одной программе, и потом запись СОХРАНЯЕТСЯ В ТУ САМУЮ ДИРЕКТОРИЮ которую мониторит моя программа - все локально. в ОДИН момент времени может быть обработан и сохранен ТОЛЬКО ОДИН ЕДИНСТВЕННЫЙ ФАЙЛ! директория всегда одна и та же, программа для записи звука всегда одна и та же. код что я накидал выше - работает, проблема возникает только в том случае если пользователь НЕ закрыл файл вручную после того как сохранил его в директории что мониторит моя программа в которой вот та часть кода что отвечает за КОПИРОВАНИЕ а потом и за ПЕРЕМЕЩЕНИЕ....

значит по опыту скажу что функция копирования работает в любом случае нормально, в не зависимости от.... да ни от чего не зависит!!! опыт гвоорит что в 100% нет проблем с копированием файлов - такова специфика, файл НЕ сохраняется до момента пока на 100% не готов, как только готов - только в тот момент он и сохраняется вручную пользователем после чего в 100% должен быть закрыт руками - когда работаю я - нет ни одной ошибки ни с копированием ни с перемещением, но у нас встречаются люди у кого есть проблемы с моторикой рук, они бывают не всегда успевают в течении ОТ 3 секунд закрыть файл, да и просто БАНАЛЬНО ЗАБЫВАЮТ!!! сразу его закрыть - копирование происходит ВСЕГДА нормально без проблем и вопросв, а вот функция перемещения вылетает с ошибкой если файл не закрыт при этом если фордж не свернут, но если он свернут или не активен то и ПЕРЕМЕЩЕНИЕ!!! срабатывает - обкрадывая Фордж, после чего когда пользователь его разворачивает обратно уже Фордж ругается что файла не существует, хотя это не страшно хуэе всего когда фордж остается активным не свернутым и с открытым файлом - вот тогда происходит конкретная ошибка IOExeption - вернее происходила! код что я начеркал выше самый свежий и протестирован был сегодня - на данный момент с этим кодом обработчик try-catch вроде стабильно работает - не вылетает с ошибкой, только каждые 10 секунд всплывающее сообщение выскакивает ну вот из этой части кода:

C#
1
notifyIcon.BalloonTipText = "Файл: " + NetFiName + " ...все еще открыт в Фордже, закройте файл!!!"; notifyIcon.ShowBalloonTip(1000);
это в том случае если фордж не свернут, и в том случае если СВЕРНУТ НО ФАЙЛ ВНУТРИ ФОРДЖА раскрыт на МАКСИМУМ!!! тогда срабатывает вот эта часть кода:

C#
1
 if (test_SF_Open != 0)
и ничего не вылетает, только сообщение в трее о том что файл все еще открыт, закройте файл...

единственная ситуация когда что то может пойти не так это когда файл не на все окно развернут в фордже при этом фордж еще и свернут должен быть или не активным (перекрыт другими окнами и потерял курсор - только в этом случае происходит операция Копирования и сразу после Перемещения но ругани нет!!! ибо когда фордж не активен он почему то дает полный доступ на файл можете сами смоделировать эту ситуацию программа SF 8.0 вполне известная и не сложна в понимании, Таймер у меня гоняет весь логический код каждые 10 секунд, то есть где то около 9 секунд программа ничего не делает, потом быстро прогоняет простейшую логику, если в директории ничего нет, на этом логика и заканчивается, ждем по таймеру еще 10 секунд и так по кругу бесконечно, но если появился файл его надо скопировать для дальнейшей работы другим людям, а нам этот файл уже не нужен (ПОСЛЕ КОПИРОВАНИЯ!!!) - но и в директории куда его только что сохранили он тоже уже не нужен ибо через 10 секунд моя прога снова его увидет и т.д. по кругу поэтому его надо ПЕРЕМЕСТИТЬ - и вот только с этим иногда происходит затык и то по вине пользователя который забыл закрыть уже СКОПИРОВАННЫЙ и уже не нужный ему файл - именно забыл, или промахнулся мышкой не попал в крестик и вместо закрытыя его сминимизировал внутри Форджа и не заметив это свернул программу а через несколько секунд моя программа наткнутвшись на это вылетает с ошибкой... вернее вылетала раньше... уже не вылетает... код что выше - уже стабилен, ошибки ВООБЩЕ не появляется ни в каких случаях, сегодня сам сидел тестировал - этот код такой вид только сегодня приобрел... у нас тут почти 2 часа ночи... кажется я уже повторяюсь в своем тексте устал... спать давно пора... последнее что хотел сказать, что вы правы - на самом деле до фене мне какой код, сколько его и т.д. - если код все эти 400 строк окажутся рабочими - то какая разница? да нет никакой разницы... завтра попробую, единственное возможно мне потребуется помощь как его оформить в виде dll или как то по другому - ну и как вызывать (какими командами и переменными переданными в эту DLL) - вобщем завтра... спасибо что пытаетесь помочь... и простите что так много текста накидал... читать вобщем то не обязательно...

Добавлено через 17 минут
не могу сократить свое сообщение, много лишнего накидал... почему так мало времени на редактирование текста дают? ничего не успеваю отредактировать... ладно в предь постараюсь быть более краток.
0
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
08.04.2019, 15:39
.. мне кажется, вы зациклились на задаче, которая принципиально поставлена неверно ... нельзя программисту доверять "моторике рук" (с) пользователя ... пользователь - человек творческий, и может создать любое состояние ... вам просто нужно пересмотреть логику вашего мониторинга в папке, например, не полагаться на единственный файл, который нужно скопировать, а прочитать через foreach список файлов, вычислить дату сохранения и последний сохраненный файл скопировать .. и пусть там лежит хоть двадцать открытых композитором свернутых файлов ... после завершения творческого дня можно всё это почистить ...
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
09.04.2019, 07:47  [ТС]
Цитата Сообщение от carrotik Посмотреть сообщение
.. мне кажется, вы зациклились на задаче, которая принципиально поставлена неверно ... нельзя программисту доверять "моторике рук" (с) пользователя ... пользователь - человек творческий, и может создать любое состояние ... вам просто нужно пересмотреть логику вашего мониторинга в папке, например, не полагаться на единственный файл, который нужно скопировать, а прочитать через foreach список файлов, вычислить дату сохранения и последний сохраненный файл скопировать .. и пусть там лежит хоть двадцать открытых композитором свернутых файлов ... после завершения творческого дня можно всё это почистить ...
Я не объяснял всю специфику и логику работы, это мой косяк, в данном случае поясню: звуковой файл записываемый звукорежиссером нужен в работе на другом этаже в другой программе прямо СРАЗУ ПОСЛЕ ЗАПИСИ, этот файл ТАМ ЖДУТ!... иногда под попой горит как ждут... так что вариант - ПУСТЬ ВАЛЯЕТСЯ СКОЛЬКО ХОЧЕТ НЕ ПОДХОДИТ, совсем никак не подходит, файл обязательно должен быть скопирован в ЛОКАЛЬНУЮ СЕТЬ для дальнейшей работы с ним, и когда он скопирован, то менять его УЖЕ НИКАК НЕЛЬЗЯ, поэтому в мониторинговой директории уже не нужен, и его надо УБРАТЬ! ибо он уже отработан и отдан "дальше по цеху"... поэтому мы его MOVE локально в Архив в другую директорию, но звукорежиссеры это люди а не роботы, они иногда ЗАБЫВАЮТ закрыть файл после сохранения, моя логика даёт время на закрытие файла от 3 секунд до 13 (в зависимости от двух таймеров один 10 секунд второй 3 секунды).

а блок foreach у меня есть в программе и не один он используется для выяснения перебора всех файлов в поисках дупликата в имени файла и изменении имени, если вдруг будет такой найден, что бы не было перезаписи уже существующего там файла...

п.с. - задача поставлена верно, если файл не закрыт сразу моя прога НЕ МОЖЕТ ПЕРЕМЕСТИТЬ его (забыли закрыть)... эта ошибка возникает невероятно редко, у меня ни разу за полгода... но вот пришел новенький и у него ПРОБЛЕМА С МОТОРИКОЙ РУК! (ДЦП, но это не повод отказывать человеку в работе) и вместо ЗАКРЫТЬ попав мышкой в крестик, он ПРОМАХИВАЕТСЯ иногда и минимизирует файл внутри форджа а не закрывает его... Тем более я знаю! что эту ошибку можно решить программно! я уже решил проблему частично, все виды ошибок этого типа исключены, кроме одного, я объяснял в ранних постах эту ситуацию: пока файл внутри форджа РАЗВЕРНУТ НА МАКС! моя прога видит это! и не позволяет выполнить Move + в трей кидает всплывающее сообщение, что вы забыли закрыть файл и т.д... если файл не закрывается через 10 секунд сообщение повторяется и так до тех пор пока его не закроют, а его в любом случае закроют ибо если не закроют он и в сети не появиться для тех кто "дальше по цеху", а от туда ОБЯЗАТЕЛЬНО ПОЗВОНЯТ через некоторое время с претензией - ГДЕ ДЕНЬГИ (ФАЙЛ) ЗИН?.. в общем варианта по прежнему ДВА:

1. Либо я добью этот код и придумаю как избежать последнего маленького нюанса с "забытым открытым файлом который не развернут на макс внутри форджа".
либо:
2. Забью на это дело и оставлю все как есть, ошибка эта возникает лишь по вине пользователя и НЕВЕРОЯТНО РЕДКО - почти никогда.

п.с. - меня зацепил факт, что я знаю, что ошибку эту можно решить програмно! а не заставлять пользователей запоминать разные нюансы работы программы.

Добавлено через 12 минут
п.п.с. - ладно я чуть позже (не уверен что сегодня, с этой ошибкой мне не к спеху можно решать сколько угодно по времени это же больше личное, чем необходимое...) в любом случае буду пробовать вариант предложенный товарищем SAU - где 400 строк програмного кода... и возможно еще вариант из темы что я указывал в первом сообщении, там человек говорил что вроде как получил готовое решение поиска названия ДОЧЕРЕНГО окна программы.
0
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
09.04.2019, 11:07
.. так пишите в лог имя и дату последнего сохраненного файла и не трогайте его потом ... но я не буду настаивать ...
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
09.04.2019, 11:33  [ТС]
Цитата Сообщение от carrotik Посмотреть сообщение
.. так пишите в лог имя и дату последнего сохраненного файла и не трогайте его потом ... но я не буду настаивать ...
я не понял о чем вы... зачем мне писать в лог имя и дату последнего сохраненного файла? мне надо УБРАТЬ файл из директории, и пока он открыт в Sound Forge (не моя программа), то попытка его MOVE (уже в моей программе) так или иначе приведет к ошибке я уже описывал проблему эту выше... зачем мне лог? что это мне даст?
0
800 / 583 / 207
Регистрация: 21.02.2019
Сообщений: 2,095
09.04.2019, 11:43
totewekotiara,
.. если вы не будете делать MOVE, а просто оставите все уже скопированные файлы в рабочей папке (копируя только последний, которого еще нет в логе), то и проблем с доступом не будет .. а когда вы будете архивировать - да хоть ночью по расписанию, когда все саунд-форджи будут закрыты ...
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
09.04.2019, 12:44  [ТС]
Цитата Сообщение от carrotik Посмотреть сообщение
totewekotiara,
.. если вы не будете делать MOVE, а просто оставите все уже скопированные файлы в рабочей папке (копируя только последний, которого еще нет в логе), то и проблем с доступом не будет .. а когда вы будете архивировать - да хоть ночью по расписанию, когда все саунд-форджи будут закрыты ...
Этот вариант понятен, но к сожалению может потянуть за собой другие проблемы, когда пользователь не закрыл файл, то через некоторое время он может не вспомнить сохранял его уже или нет и ПЕРЕСОХРАНИТЬ туда же в эту же директорию - если он не менялся, то этот факт не беда - но у нас каждый день случаются так называемые "исправления" только что начитанного текста и вот тут может начаться путаница, что куда ПЕРЕЗАПИСЫВАЛОСЬ а что нет, поэтому мы любые исправления ВСЕГДА пишем в новый файл... должен быть ПОРЯДОК, если файл был сохранен, его в 100% случаях надо ЗАКРЫТЬ и в 100% случаях как можно скорее убрать из директории что бы пользователю не пришла в голову идея перезаписать туда какие нибудь "перечитки", порядок должен быть, он уже определен, я ни за что не поверю что эту задачу нельзя решить программным способом, к тому же она уже почти решена.

Да и если уж искать костыли обхода задачи можно придумать например вот что:

1. Как только файл сохранен, моя программа САМА будет закрывать SF без участия пользователя и не придется даже проверку делать... костыль номер раз.

2. Как только файл сохранен, моя программа легко найдет SF - принудительно его поставит на передний план передав ему курсор и тут же проверить на "вшивость" командой move файл который только что появился в контролируемой директории, а дальше сработает блок try catch который уже работает без ошибок на 100%... костыль номер два.

п.с. если еще подумать думаю можно еще костылей напридумывать, но зачем? как по мне надо просто попробовать из тех вариантов что предложил SAU или вообще тот вариант что предложил парень вот из этой темы:

Узнать дескриптор окна запускаемой программы

разобраться в нём и взять нужный код к себе в программу, но я пока еще не разобрался в этом коде, я уже говорил что программирование для меня больше ХОББИ, я пишу 1-2 программы в 10 лет и то для себя последнее (до этих вот двух в 2018-2019) что я писал было во времена Дельфи 4 а до него во времена FOX PRO когда еще Win95 даже не вышел... старый я уже для дотошного разбирательства и учебы... прошло мое время, теперь только для себя в виде хобби...
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
11.04.2019, 08:34  [ТС]
Цитата Сообщение от sau Посмотреть сообщение
GetProcessesLockingFile - возвращает список процессов блокирующих работу с файлом , в вашем случае достаточно убедится , что список пустой , после чего с файлом можно работать.
попробовал 400 строк, ничего не получилось, открыт файл или закрыт, даже если его не существует, ответ всегда одинаковый... оформил я все это для тестов вот так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
 
namespace Получить_Заголовок_Окна
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            // var fstream = new FileStream(@"путь до файла", FileMode.Open, FileAccess.Read, FileShare.Read);
 
            string test = @"f:\RABOTA\temp_auto\Sound 1.wav";
 
            label1.Text = "t1 = " + Win32Processes.GetProcessesLockingFile(test);
            label2.Text = "File.Exists(test) = " + File.Exists(test);
 
 
        }
 
        public class Win32Processes
        {
            /// <summary>
            /// Return a list of processes that hold on the given file.
            /// </summary>
            public static List<Process> GetProcessesLockingFile(string filePath)
            {
                var procs = new List<Process>();
 
                var processListSnapshot = Process.GetProcesses();
                foreach (var process in processListSnapshot)
                {
                    if (process.Id <= 4) { continue; } // system processes
                    var files = GetFilesLockedBy(process);
                    if (files.Contains(filePath)) procs.Add(process);
                }
                return procs;
            }
 
            /// <summary>
            /// Return a list of file locks held by the process.
            /// </summary>
            public static List<string> GetFilesLockedBy(Process process)
            {
                var outp = new List<string>();
 
                ThreadStart ts = delegate
                {
                    try
                    {
                        outp = UnsafeGetFilesLockedBy(process);
                    }
                    catch { Ignore(); }
                };
 
                try
                {
                    var t = new Thread(ts);
                    t.IsBackground = true;
                    t.Start();
                    if (!t.Join(250))
                    {
                        try
                        {
                            t.Interrupt();
                            t.Abort();
                        }
                        catch { Ignore(); }
                    }
                }
                catch { Ignore(); }
 
                return outp;
            }
 
 
            #region Inner Workings
            private static void Ignore() { }
            private static List<string> UnsafeGetFilesLockedBy(Process process)
            {
                try
                {
                    var handles = GetHandles(process);
                    var files = new List<string>();
 
                    foreach (var handle in handles)
                    {
                        var file = GetFilePath(handle, process);
                        if (file != null) files.Add(file);
                    }
 
                    return files;
                }
                catch
                {
                    return new List<string>();
                }
            }
 
            const int CNST_SYSTEM_HANDLE_INFORMATION = 16;
            private static string GetFilePath(Win32API.SYSTEM_HANDLE_INFORMATION systemHandleInformation, Process process)
            {
                var ipProcessHwnd = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, false, process.Id);
                var objBasic = new Win32API.OBJECT_BASIC_INFORMATION();
                var objObjectType = new Win32API.OBJECT_TYPE_INFORMATION();
                var objObjectName = new Win32API.OBJECT_NAME_INFORMATION();
                var strObjectName = "";
                var nLength = 0;
                IntPtr ipTemp, ipHandle;
 
                if (!Win32API.DuplicateHandle(ipProcessHwnd, systemHandleInformation.Handle, Win32API.GetCurrentProcess(), out ipHandle, 0, false, Win32API.DUPLICATE_SAME_ACCESS))
                    return null;
 
                IntPtr ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic));
                Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectBasicInformation, ipBasic, Marshal.SizeOf(objBasic), ref nLength);
                objBasic = (Win32API.OBJECT_BASIC_INFORMATION)Marshal.PtrToStructure(ipBasic, objBasic.GetType());
                Marshal.FreeHGlobal(ipBasic);
 
                IntPtr ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength);
                nLength = objBasic.TypeInformationLength;
                // this one never locks...
                while ((uint)(Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectTypeInformation, ipObjectType, nLength, ref nLength)) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
                {
                    if (nLength == 0)
                    {
                        Console.WriteLine("nLength returned at zero! ");
                        return null;
                    }
                    Marshal.FreeHGlobal(ipObjectType);
                    ipObjectType = Marshal.AllocHGlobal(nLength);
                }
 
                objObjectType = (Win32API.OBJECT_TYPE_INFORMATION)Marshal.PtrToStructure(ipObjectType, objObjectType.GetType());
                if (Is64Bits())
                {
                    ipTemp = new IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32);
                }
                else
                {
                    ipTemp = objObjectType.Name.Buffer;
                }
 
                var strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1);
                Marshal.FreeHGlobal(ipObjectType);
                if (strObjectTypeName != "File")
                    return null;
 
                nLength = objBasic.NameInformationLength;
 
                var ipObjectName = Marshal.AllocHGlobal(nLength);
 
                // ...this call sometimes hangs. Is a Windows error.
                while ((uint)(Win32API.NtQueryObject(ipHandle, (int)Win32API.ObjectInformationClass.ObjectNameInformation, ipObjectName, nLength, ref nLength)) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
                {
                    Marshal.FreeHGlobal(ipObjectName);
                    if (nLength == 0)
                    {
                        Console.WriteLine("nLength returned at zero! " + strObjectTypeName);
                        return null;
                    }
                    ipObjectName = Marshal.AllocHGlobal(nLength);
                }
                objObjectName = (Win32API.OBJECT_NAME_INFORMATION)Marshal.PtrToStructure(ipObjectName, objObjectName.GetType());
 
                if (Is64Bits())
                {
                    ipTemp = new IntPtr(Convert.ToInt64(objObjectName.Name.Buffer.ToString(), 10) >> 32);
                }
                else
                {
                    ipTemp = objObjectName.Name.Buffer;
                }
 
                if (ipTemp != IntPtr.Zero)
                {
 
                    var baTemp = new byte[nLength];
                    try
                    {
                        Marshal.Copy(ipTemp, baTemp, 0, nLength);
 
                        strObjectName = Marshal.PtrToStringUni(Is64Bits() ? new IntPtr(ipTemp.ToInt64()) : new IntPtr(ipTemp.ToInt32()));
                    }
                    catch (AccessViolationException)
                    {
                        return null;
                    }
                    finally
                    {
                        Marshal.FreeHGlobal(ipObjectName);
                        Win32API.CloseHandle(ipHandle);
                    }
                }
 
                string path = GetRegularFileNameFromDevice(strObjectName);
                try
                {
                    return path;
                }
                catch
                {
                    return null;
                }
            }
 
            private static string GetRegularFileNameFromDevice(string strRawName)
            {
                string strFileName = strRawName;
                foreach (string strDrivePath in Environment.GetLogicalDrives())
                {
                    var sbTargetPath = new StringBuilder(Win32API.MAX_PATH);
                    if (Win32API.QueryDosDevice(strDrivePath.Substring(0, 2), sbTargetPath, Win32API.MAX_PATH) == 0)
                    {
                        return strRawName;
                    }
                    string strTargetPath = sbTargetPath.ToString();
                    if (strFileName.StartsWith(strTargetPath))
                    {
                        strFileName = strFileName.Replace(strTargetPath, strDrivePath.Substring(0, 2));
                        break;
                    }
                }
                return strFileName;
            }
 
            private static IEnumerable<Win32API.SYSTEM_HANDLE_INFORMATION> GetHandles(Process process)
            {
                var nHandleInfoSize = 0x10000;
                var ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize);
                var nLength = 0;
                IntPtr ipHandle;
 
                while (Win32API.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer, nHandleInfoSize, ref nLength) == Win32API.STATUS_INFO_LENGTH_MISMATCH)
                {
                    nHandleInfoSize = nLength;
                    Marshal.FreeHGlobal(ipHandlePointer);
                    ipHandlePointer = Marshal.AllocHGlobal(nLength);
                }
 
                var baTemp = new byte[nLength];
                Marshal.Copy(ipHandlePointer, baTemp, 0, nLength);
 
                long lHandleCount;
                if (Is64Bits())
                {
                    lHandleCount = Marshal.ReadInt64(ipHandlePointer);
                    ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8);
                }
                else
                {
                    lHandleCount = Marshal.ReadInt32(ipHandlePointer);
                    ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4);
                }
 
                var lstHandles = new List<Win32API.SYSTEM_HANDLE_INFORMATION>();
 
                for (long lIndex = 0; lIndex < lHandleCount; lIndex++)
                {
                    var shHandle = new Win32API.SYSTEM_HANDLE_INFORMATION();
                    if (Is64Bits())
                    {
                        shHandle = (Win32API.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                        ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8);
                    }
                    else
                    {
                        ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle));
                        shHandle = (Win32API.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType());
                    }
                    if (shHandle.ProcessID != process.Id) continue;
                    lstHandles.Add(shHandle);
                }
                return lstHandles;
            }
 
            private static bool Is64Bits()
            {
                return Marshal.SizeOf(typeof(IntPtr)) == 8;
            }
 
            internal class Win32API
            {
                [DllImport("ntdll.dll")]
                public static extern int NtQueryObject(IntPtr ObjectHandle, int
                    ObjectInformationClass, IntPtr ObjectInformation, int ObjectInformationLength,
                    ref int returnLength);
 
                [DllImport("kernel32.dll", SetLastError = true)]
                public static extern uint QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);
 
                [DllImport("ntdll.dll")]
                public static extern uint NtQuerySystemInformation(int
                    SystemInformationClass, IntPtr SystemInformation, int SystemInformationLength,
                    ref int returnLength);
 
                [DllImport("kernel32.dll")]
                public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId);
                [DllImport("kernel32.dll")]
                public static extern int CloseHandle(IntPtr hObject);
                [DllImport("kernel32.dll", SetLastError = true)]
                [return: MarshalAs(UnmanagedType.Bool)]
                public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
                   ushort hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
                   uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
                [DllImport("kernel32.dll")]
                public static extern IntPtr GetCurrentProcess();
 
                public enum ObjectInformationClass
                {
                    ObjectBasicInformation = 0,
                    ObjectNameInformation = 1,
                    ObjectTypeInformation = 2,
                    ObjectAllTypesInformation = 3,
                    ObjectHandleInformation = 4
                }
 
                [Flags]
                public enum ProcessAccessFlags : uint
                {
                    All = 0x001F0FFF,
                    Terminate = 0x00000001,
                    CreateThread = 0x00000002,
                    VMOperation = 0x00000008,
                    VMRead = 0x00000010,
                    VMWrite = 0x00000020,
                    DupHandle = 0x00000040,
                    SetInformation = 0x00000200,
                    QueryInformation = 0x00000400,
                    Synchronize = 0x00100000
                }
 
                [StructLayout(LayoutKind.Sequential)]
                public struct OBJECT_BASIC_INFORMATION
                { // Information Class 0
                    public int Attributes;
                    public int GrantedAccess;
                    public int HandleCount;
                    public int PointerCount;
                    public int PagedPoolUsage;
                    public int NonPagedPoolUsage;
                    public int Reserved1;
                    public int Reserved2;
                    public int Reserved3;
                    public int NameInformationLength;
                    public int TypeInformationLength;
                    public int SecurityDescriptorLength;
                    public System.Runtime.InteropServices.ComTypes.FILETIME CreateTime;
                }
 
                [StructLayout(LayoutKind.Sequential)]
                public struct OBJECT_TYPE_INFORMATION
                { // Information Class 2
                    public UNICODE_STRING Name;
                    public int ObjectCount;
                    public int HandleCount;
                    public int Reserved1;
                    public int Reserved2;
                    public int Reserved3;
                    public int Reserved4;
                    public int PeakObjectCount;
                    public int PeakHandleCount;
                    public int Reserved5;
                    public int Reserved6;
                    public int Reserved7;
                    public int Reserved8;
                    public int InvalidAttributes;
                    public GENERIC_MAPPING GenericMapping;
                    public int ValidAccess;
                    public byte Unknown;
                    public byte MaintainHandleDatabase;
                    public int PoolType;
                    public int PagedPoolUsage;
                    public int NonPagedPoolUsage;
                }
 
                [StructLayout(LayoutKind.Sequential)]
                public struct OBJECT_NAME_INFORMATION
                { // Information Class 1
                    public UNICODE_STRING Name;
                }
 
                [StructLayout(LayoutKind.Sequential, Pack = 1)]
                public struct UNICODE_STRING
                {
                    public ushort Length;
                    public ushort MaximumLength;
                    public IntPtr Buffer;
                }
 
                [StructLayout(LayoutKind.Sequential)]
                public struct GENERIC_MAPPING
                {
                    public int GenericRead;
                    public int GenericWrite;
                    public int GenericExecute;
                    public int GenericAll;
                }
 
                [StructLayout(LayoutKind.Sequential, Pack = 1)]
                public struct SYSTEM_HANDLE_INFORMATION
                { // Information Class 16
                    public int ProcessID;
                    public byte ObjectTypeNumber;
                    public byte Flags; // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                    public ushort Handle;
                    public int Object_Pointer;
                    public UInt32 GrantedAccess;
                }
 
                public const int MAX_PATH = 260;
                public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
                public const int DUPLICATE_SAME_ACCESS = 0x2;
                public const uint FILE_SEQUENTIAL_ONLY = 0x00000004;
            }
            #endregion
        }
 
 
    }
 
}
при нажатии на кнопку на 5-6 секунд все подвисает чутка, потом в первой лейбе всегда одна и та же надпись:

System.Collections.Generic.List`1[System.Diagnostics.Process]

и не важно открыт файл или закрыт, вообще даже если его не существует... еще программа с этим кодом с непонятной переодичностью может просто вылететь с ошибкой отладки... проблема не решена...
0
Эксперт .NET
6691 / 4102 / 1607
Регистрация: 09.05.2015
Сообщений: 9,569
11.04.2019, 08:37
Цитата Сообщение от totewekotiara Посмотреть сообщение
при нажатии на кнопку на 5-6 секунд все подвисает чутка, потом в первой лейбе всегда одна и та же надпись:
System.Collections.Generic.List`1[System.Diagnostics.Process]
и не важно открыт файл или закрыт, вообще даже если его не существует... еще программа с этим кодом с непонятной переодичностью может просто вылететь с ошибкой отладки... проблема не решена...
Пройтись по списку циклом религия не позволяет?
0
 Аватар для sau
2773 / 2073 / 386
Регистрация: 22.07.2011
Сообщений: 7,820
11.04.2019, 12:17
Цитата Сообщение от totewekotiara Посмотреть сообщение
System.Collections.Generic.List`1[System.Diagnostics.Process]
кто же список к строке так приводит ? )

C#
1
2
var processList = Win32Processes.GetProcessesLockingFile(test);
if(processList.Count) label1.Text = "файл занят";
Цитата Сообщение от Someone007 Посмотреть сообщение
на 5-6 секунд все подвисает чутка
Можно ускорить, если воспользоваться функцией GetFilesLockedBy - для одного процесса.

Цитата Сообщение от Someone007 Посмотреть сообщение
еще программа с этим кодом с непонятной переодичностью может просто вылететь с ошибкой отладки
ну , в этом коде много специфичных апи функций дергается , и не факт , что все они четко обрабатываются , например
Win32API.NtQuerySystemInformation , кроме STАTUS_INFO_LЕNGTH_MISMАTCH или NT_SUCCЕSS , может вернуть и другой результат , который никак тут не учтен. Полагаю , если сократить считывание до одного процесса , можно минимизировать возможные ошибки. , и оберните ее вызов блоком try/catch , дабы выявить источник проблемы.
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
12.04.2019, 04:12  [ТС]
Цитата Сообщение от sau Посмотреть сообщение
var processList = Win32Processes.GetProcessesLockingFile(t est);
if(processList.Count) label1.Text = "файл занят";
C#
1
if (processList.Count) label1.Text = "файл занят";
- Не удается не явно преобразовать Int в Bool... другими словами - ошибка еще на стадии компиляции...

пошел другим путем, сделал так:

C#
1
label2.Text = "processList.Count = " + processList.Count;
- результат всегда один и тот же = 0. ничего я так и не выяснил при помощи данного метода... обернул в тру-катч, таким образом:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    string test = @"f:\RABOTA\temp_auto\Sound 1.wav";
            try
            {
                var processList = Win32Processes.GetProcessesLockingFile(test);
                if (processList.Count == 1) label1.Text = "файл занят";
                label2.Text = "processList.Count = " + processList.Count;
                if (File.Exists(test))
                {
                    label3.Text = "File.Exists(test) = " + File.Exists(test);
                }
 
            }
            catch (Exception ex)
            {
                label2.Text = "Ошибка: " +ex.Message;
            }
пару раз вылетала с ОШИБКОЙ ОТЛАДКИ БЕЗ ВОЗМОЖНОСТИ ДАЖЕ ПОСМОТРЕТЬ ЧТО ЗА ОШИБКА!!! то есть окно было не NET а другое попробую повторить эту ошибку и заскриншотить это окно...



п.с. - Решение НЕ НАЙДЕНО. есть еще идеи?
0
0 / 0 / 0
Регистрация: 05.04.2019
Сообщений: 10
12.04.2019, 05:27  [ТС]
Цитата Сообщение от sau Посмотреть сообщение
Можно ускорить, если воспользоваться функцией GetFilesLockedBy - для одного процесса.
попробовал вот так:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
            public static List<Process> GetProcessesLockingFile(string filePath)
            {
                var procs = new List<Process>();
 
                var processListSnapshot = Process.GetProcessesByName("Forge80");
                foreach (var process in processListSnapshot)
                {
                    if (process.Id <= 4) { continue; } // system processes
                    var files = GetFilesLockedBy(process);
                    if (files.Contains(filePath)) procs.Add(process);
                }
                return procs;
            }

ответ тот же = 0. но зато все быстрее стало - почти мгновенно, без задержек... или я опять не так сделал что то???

то ли метод не рабочий... то ли еще где то что то не так... я не знаю..., но например вот эта одна строка:

C#
1
var fstream = new FileStream(@"путь до файла", FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
работает! но только до того момента пока Forge80 не потерял курсор... кому вообще пришла в голову "блестящая" идея так ИЗДЕВАТЬСЯ... если файл открыт в программе, то В НЕ ЗАВИСИМОСТИ свернута программа или нет, параметр FileAccess.ReadWrite должен возвращать ошибку а не как у меня получается - ПОЛНЫЙ ДОСТУП - делай что хочешь с файлом... я не ожидал такой подставы от современников..., хотя тенденцию эту наблюдаю давно к сожалению... п.с. если кто не понял то поясняю, при попытке создать FileStream с параметром FileAccess.ReadWrite для файла который открыт в Forge80.exe - выскакивает исключение которое ОТЛИЧНО обрабатывается в трай-кетч с ошибкой доступа к файлу - и это бы решило мою проблему если бы не одна маленькая "засада" - все это в 100% работает только до момента пока Forge80 активен (курсор на нем и он не свернут на панель задач или не перекрыт любым другим окном чего угодно) - кому в голову может в фирме СОНИ (а может это особенности новых фишек операционок современных я не знаю не копал так глубоко) что при потере курсора отдавать полный доступ до файла который ВСЕ ЕЩЕ ОТКРЫТ В ПРОГРАММЕ!!! что за бред??? у меня вся эта "СТРАННАЯ ЛОГИКА" в голове не укладывается... а я еще ломал раньше голову почему иногда ФОРДЖ файл теряет а иногда нет, хотя файл был ДО этого сохранен на диск - но нет, если файл открытым остался и ДАЖЕ ЕСЛИ ЕГО СОХРАНЯЛИ - он все равно может оказаться СЛОМАННЫМ или вообще исчезнуть из ТАБИЛЦЫ ФАЙЛОВ если перезагрузить комп кнопкой ресет например (эта проблема оборудования некоторого специфического - есть у нас старое оборудование которе время от времени может один раз в неделю а может и ни разу за полгода, а иногда и два три раза в день) - перезагрузить комп в совершенно любой момент - хоть занят чем то хоть совершенно ничем не занят... получается что пока файл был открыт его и НЕ СУЩЕСТВОВАЛО в Таблице Файлов (хотя до этого его уже сохраняли и он появлялся в эксплрере его видно было) но его все равно не было пока файл открытым был в Forge при этом при всем еще и это:

C#
1
var fstream = new FileStream(@"путь до файла", FileMode.Open, FileAccess.ReadWrite, FileShare.Read);
не работает как должно (скорее всего эта вина именно непосредственно самой программы Саунд Фордж а не проверочного кода) - но мне от этого не легче, из-за чьей то недоработки почти любая логика проверок не может выдавать 100% метод - при этом на операции ЧТЕНИЯ-ЗАПИСИ - то есть операции ВВОДА-ВЫВОДА - те самые которые лежат в НАИПЕРВЕЙШЕЙ ОСНОВЕ любо ОС в любой момент времени в любом месте... бред какой то...

п.с. - извените за БРЮЗЖАНИЕ - просто накипело...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
12.04.2019, 05:27
Помогаю со студенческими работами здесь

Как можно узнать используется ли файл в данный момент другой программой
Здравствуйте. Одна программа раз в несколько секунд пишет в файл некоторые параметры. Мне раз в несколько минут нужно их забрать и...

Как проверить открыт\закрыт порт по внешнему IP
Собственно вопрос в теме... Как сделать проверку порта по моему внешнему IP и вывести в лабл значение? Допустим если 80 порт открыт то в...

Как проверить открыт порт или закрыт
Привет! Подскажите как проверить на АРМ открыт порт или закрыт например (110), желательно ч/з cmd?

Как проверить, открыт или закрыт порт по внешнему IP?
Доброго утрица всем... Собственно вопрос в шапке... Нужно проверить порт(закрыт он или открыт) по внешнему IP... Когда то мной была создана...

Как мне сделать так, чтобы данный текстовый файл был открыт один раз при запуске программы и закрыт при закрытии программы?
Привет! Возник следующий вопрос. Программа состоит из основного окна Form1 и нескольких Unit. По таймеру в Form1 запускается один из...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru