Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
.NET 4.x

WinApi и работа с альтернативными файловыми потоками

15.07.2016, 17:40. Показов 3803. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток.
Пытаюсь разобраться с работой альтернативных файловых потоков в NTFS.
Как я понял из C# с ними можно работать только через WinApi (CreateFile, WriteFile и ReadFile).
Соответственно написал для этих функцию обёртку.
С Create и Write проблем нет. Возникли проблемы с чтением. Функция отрабатывает, возвращает True, но данные не получает. При этом данные в альтернативный файловый поток точно записываются, проверял из командной строки.

Функции класса обёртки WinApi*:
Кликните здесь для просмотра всего текста

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
        // Импорт функции CreateFile
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr CreateFile(
            string lpFileName,
            uint dwDesiredAccess,
            uint dwShareMode,
            IntPtr lpSecurityAttributes,
            byte dwCreationDisposition,
            short dwFlagsAndAttributes,
            IntPtr hTemplateFile);
 
        // Импорт функции ReadFile
        [DllImport("kernel32", SetLastError = true)]
        private static extern unsafe bool ReadFile(IntPtr _hFile, void* _lpBuffer, uint _nNumberOfBytesToRead, uint* _lpNumberOfBytesRead, uint _lpOverlapped);
 
        // Импорт функции WriteFile
        [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
        static extern bool WriteFile(IntPtr hFile, byte[] lpBuffer, uint nNumberOfBytesToWrite, ref int N, int N1);
 
        // Импорт функции CloseHandle
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool CloseHandle(IntPtr hObject);
 
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern int GetLastError();
 
  // Конструктор класса
        // s - путь к файлу или устройство
        public LDrive(string s, byte Metod)
        {
            pl = CreateFile(s, GENERIC_READ | GENERIC_WRITE, 0, IntPtr.Zero, Metod, 0x80, IntPtr.Zero);
        }
 
        // Закрыть хендл
        public bool close()
        {
            return CloseHandle(this.pl);
        }
 
        // Записать
        public bool Write(byte[] buf, uint NofBytesToWrite)
        {
            return WriteFile(this.pl, buf, NofBytesToWrite, ref N, 0);
        }
 
        // Получить код ошибки
        public int Error()
        {
            return GetLastError();
        }
 
        // Прочитать
        public bool Read(ref byte[] buf, uint NofBytesToRead)
        {
            unsafe
            {
                fixed (void* pvPacket = buf)
                {
                    uint readingbytes = 0;
                    bool isOk = ReadFile(this.pl, pvPacket, (uint)buf.Length, &readingbytes, 0);
                    return isOk;
                }
            }          
        }


Код, которым пытаюсь прочитать данные:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        static byte Create = 2;
        static byte Open = 3;
        static string MyStream = "MyStream";
        static LDrive drive = new LDrive(@"H:\1.txt:" + MyStream, Open);
 
        static void Main(string[] args)
        {
            if ((int)drive.pl == -1)
                Console.WriteLine(drive.Error());
            //byte[] outData = Encoding.Unicode.GetBytes("Это скрытый текст");
           // if (!drive.Write(outData, (uint)outData.Length))
               // Console.WriteLine(drive.Error());
            byte[] buf = new byte[512];
            if (!drive.Read(ref buf, 512))
                Console.WriteLine(drive.Error());
            drive.close();
            Console.ReadKey();
        }


* чтобы не изобретать велосипед, взял сигнатуры, найденные в сети. Вроде ошибок в них не вижу. Создание хэндла и запись в файл работают точно.

С pInvoke вообще и WinApi в частности дел почти не имел, мог где-то глупо накосячить. Прошу помощи более опытных коллег.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.07.2016, 17:40
Ответы с готовыми решениями:

Работа с потоками
У меня приложение через заданный интервал (в таймере) отправляет запрос на сайт и парсит ответ, при отправке запросов приложение подвисает,...

Работа с потоками
Ребята, помогите. На C# программирую недавно, про потоки слышу впервые. Подскажите как это можно реализовать в VS2005. 1. Warcraft....

работа с потоками
При работе с методом выдает ошибку: "Недопустимая операция в нескольких потоках: попытка доступа к элементу управления...

8
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18240 / 14154 / 5366
Регистрация: 17.03.2014
Сообщений: 28,841
Записей в блоге: 1
15.07.2016, 19:41
Лучший ответ Сообщение было отмечено aquaMakc как решение

Решение

aquaMakc, можно проще. С минимумом p/invoke, без указателей и unsafe кода. Достаточно вызвать только CreateFile, получить от неё дескриптор, обернуть вокруг него FileStream и дальше использовать .NET классы:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static void Main(string[] args)
{
    using (var fstream = FileStreamHelper.OpenWithStream(@"d:\11111", "MyStream", FileMode.Create, FileAccess.Write))
    using (var writer = new StreamWriter(fstream, Encoding.Unicode))
    {
        writer.Write("Это скрытый текст");
    }
    using (var fstream = FileStreamHelper.OpenWithStream(@"d:\11111", "MyStream", FileMode.Open, FileAccess.Read))
    using (var reader = new StreamReader(fstream, Encoding.Unicode))
    {
        Console.WriteLine(reader.ReadToEnd());
    }
    Console.ReadKey();
}
FileStreamHelper
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
using System.IO;
using Microsoft.Win32.SafeHandles;
 
public static class FileStreamHelper
{
    public static FileStream OpenWithStream(string fileName, string streamName, FileMode mode, FileAccess access)
    {
        return OpenWithStream(fileName, streamName, mode, access, FileShare.None);
    }
    
    public static FileStream OpenWithStream(string fileName, string streamName, FileMode mode, FileAccess access, FileShare share)
    {
        uint desiredAccess = (access & FileAccess.Read) == FileAccess.Read ? GenericRead : 0;
        desiredAccess |= (access & FileAccess.Write) == FileAccess.Write ? GenericWrite : 0;
        
        SafeFileHandle fileHandle = CreateFile(
            fileName + ":" + streamName,
            desiredAccess,
            share,
            IntPtr.Zero,
            mode,
            FileAttributes.Normal,
            IntPtr.Zero
        );
        if (fileHandle.IsInvalid)
        {
            int win32error = Marshal.GetLastWin32Error();
            Marshal.ThrowExceptionForHR(win32error);
            switch(win32error)
            {
                case 2:
                    throw new FileNotFoundException("Failed to open file with specified stream", fileName + ":" + streamName);
                default:
                    throw new IOException("Failed to open file with specified stream");
            }
        }
        return new FileStream(fileHandle, access);
    }
 
    const uint GenericRead = 0x80000000;
    const uint GenericWrite = 0x40000000;
 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern SafeFileHandle CreateFile(
        string fileName,
        uint desiredAccess,
        [MarshalAs(UnmanagedType.U4)] FileShare share,
        IntPtr lpSecurityAttributes,
        [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
        [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
        IntPtr hTemplateFile
    );
}
3
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
15.07.2016, 23:03  [ТС]
OwenGlendower, грац, выглядит рабоче. Но только в понедельник смогу до IDE добраться.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
15.07.2016, 23:52
OwenGlendower, 2 вопроса по коду
1) зачем после ThrowExceptionForHR делать свитч, он же вроде недостижим?
2) Насколько я помню, код ошибки и HResult это разные коды (возвращаемые GetHRForLastWin32Error и GetLastWin32Error соответственно)
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18240 / 14154 / 5366
Регистрация: 17.03.2014
Сообщений: 28,841
Записей в блоге: 1
16.07.2016, 01:01
Psilon, 1) ThrowExceptionForHR не всегда генерирует исключение, поэтому switch достижим. Я тестировал это на ситуации с несуществующим файлом.

2) ты прав. Это разные вещи. Я пытался съэкономить себе работу по генерации исключений, но допустил ошибку. Собственно из-за путаницы между кодом и hresult-ом метод ThrowExceptionForHR не генерировал исключения. Можно переписать генерацию исключений так:
C#
1
2
3
4
5
6
7
8
if (fileHandle.IsInvalid)
{
    int win32error = Marshal.GetLastWin32Error();
    int hresult = (win32error & 0x0000FFFF) | unchecked((int)0x80070000);
    Exception ex = Marshal.GetExceptionForHR(hresult);
    if (ex != null) throw ex;
    throw new System.ComponentModel.Win32Exception(win32error, string.Format("Failed to open file with specified stream: '{0}'", path));
}
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
16.07.2016, 01:43
OwenGlendower, а зачем это делать руками, если я правильно помню, то marshal это и делает?..
C#
1
2
3
4
5
6
7
8
9
10
        [System.Security.SecurityCritical]  // auto-generated_required 
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        public static int GetHRForLastWin32Error()
        {
            int dwLastError = GetLastWin32Error(); 
            if ((dwLastError & 0x80000000) == 0x80000000)
                return dwLastError; 
            else 
                return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
        }
Соответственно:
C#
1
2
3
int hresult = Marshal.GetHRForLastWin32Error();
Exception ex = Marshal.GetExceptionForHR(hresult);
throw ex ?? new Win32Exception(hresult, string.Format("Failed to open file with specified stream: '{0}'", path));
Добавлено через 2 минуты
Возможно Marshal не возвращал именно потому что не было проверки на 0x80000000, тогда он неправильно складывался с 0x80070000 и получалась неверная маска, по которой он не мог вернуть исключение.
0
Администратор
Эксперт .NET
 Аватар для OwenGlendower
18240 / 14154 / 5366
Регистрация: 17.03.2014
Сообщений: 28,841
Записей в блоге: 1
16.07.2016, 08:14
Psilon, делаю руками по WinAPI привычке получать код ошибки один раз и работать с ним. Нам здесь нужно два кода - HResult для GetHRForLastWin32Error и Win32Error для класса Win32Exception.
0
Master of Orion
Эксперт .NET
 Аватар для Psilon
6101 / 4957 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
16.07.2016, 09:05
OwenGlendower, и все же я думаю, что проблема именно в этом
Например если код ошибки 0x92345678 то по твоему алгоритму получается 0x80075678, а по майкровостовскому 0x92345678.
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
18.07.2016, 09:04  [ТС]
OwenGlendower, ) работает. Можно начинать встраивать в своё ПО вирусы *шутка*
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
18.07.2016, 09:04
Помогаю со студенческими работами здесь

Работа с потоками
Добрые люди дайте готовый кусочек кода по работе с потоками Требования такие Запустив энное количество потоков мне надо дождаться их...

Работа с потоками
Доброе время суток подскажите пож как реализовать : "Шарики. Координаты заданного количества шариков изменяются на случайную величину по...

Работа с потоками
Здравствуйте. Проблема заключается в следующем, в параллельном потоке мне нужно чтобы label1 созданный в основном потоке, изменялся....

Работа с потоками...
Понимаю, что тема проезжена и не раз, однако спрошу:-[: Есть консольное приложение, оно занимается подсчетом сообщений. По запросу оно...

Работа с байтовыми потоками
Доброго времени суток. Столкнулся с такой проблемой , имеется файл(песня mp3) необходим считать из него скажем первые 10 байт и потом...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
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 . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru