Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: вызов GetVolumeInformationW  (Прочитано 20046 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 14-01-2012 13:40 » 

забавная проблема: если вызывать функцию GetVolumeInformationW из C++, то всё ок, если из шарпа - GetLastError возвращает ошибку 123 (Синтаксическая ошибка в имени файла, имени папки или метке тома. )

вызываю так
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;//WinAPI

namespace GetDriveSerialNumber
{
public partial class Form1:Form
{

[DllImport("Kernel32.dll",EntryPoint="GetVolumeInformationW")]
public static extern int GetVolumeInformationW
(
   String lpRootPathName          ,
out String lpVolumeNameBuffer      ,
   uint   nVolumeNameSize         ,
out uint   lpVolumeSerialNumber    ,
out uint   lpMaximumComponentLength,
out uint   lpFileSystemFlags       ,
out String lpFileSystemNameBuffer  ,
   uint   nFileSystemNameSize
);

[DllImport("Kernel32.dll",EntryPoint="GetLastError")]
public static extern uint GetLastError
(
);

public Form1()
{
InitializeComponent();
}

private void but_getinfo_Click(object sender,EventArgs e)
{
String lpRootPathName          ="E:\\";
String lpVolumeNameBuffer      ;
uint   nVolumeNameSize         = 255;
uint   lpVolumeSerialNumber    ;
uint   lpMaximumComponentLength;
uint   lpFileSystemFlags       ;
String lpFileSystemNameBuffer  ;
uint   nFileSystemNameSize     = 255;

if(0!=GetVolumeInformationW
(
     lpRootPathName          ,
out lpVolumeNameBuffer      ,
     nVolumeNameSize         ,
out lpVolumeSerialNumber    ,
out lpMaximumComponentLength,
out lpFileSystemFlags       ,
out lpFileSystemNameBuffer  ,
nFileSystemNameSize

)
)
{

}

uint err=GetLastError();
}
}
}

что не так ? Как-то юникодную строку неправильно заполняю ?

Код:
String lpRootPathName          ="E:\\";
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 14-01-2012 16:02 » 

Алексей1153++, в параметрах атрибута DllImport кодировку укажи - по умолчанию ANSI.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #2 : 14-01-2012 16:32 » 

точно, ты же мне раньше показывал, а я и забыл )) Спасиб

Добавлено через 8 минут и 5 секунд:
а вот со строками сообразить опять не могу , как выделить место в 255 символов, чтобы АПИшная функция смогла туда записать данные ?
« Последнее редактирование: 14-01-2012 16:40 от Алексей1153 » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 14-01-2012 22:05 » 

Алексей1153++, ты сначала попробуй просто out string. И если не заработает, тогда покажу вариант через Marshal.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #4 : 15-01-2012 06:22 » 

ругается. Ожидаемо


* err1.gif (46.37 Кб - загружено 1760 раз.)
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 15-01-2012 07:25 » 

Алексей1153++, а где у тебя ref на этом параметре, если он двунаправленный?

Добавлено через 17 минут и 35 секунд:
Так, я добрался до MSDN.

Цитата
BOOL WINAPI GetVolumeInformationByHandleW(
  __in          HANDLE hFile,
  __out         LPTSTR lpVolumeNameBuffer,
  __in          DWORD nVolumeNameSize,
  __out         LPDWORD lpVolumeSerialNumber,
  __out         LPDWORD lpMaximumComponentLength,
  __out         LPDWORD lpFileSystemFlags,
  __out         LPTSTR lpFileSystemNameBuffer,
  __in          DWORD nFileSystemNameSize
);

Это переводится следующим образом. Все LPTSTR - в string, все HANDLE в IntPtr, все DWORD в uint. Все out параметры должны также помечаться out в C#.

С LPDWORD нужно разбираться подробно.

Цитата

lpVolumeSerialNumber
A pointer to a variable that receives the volume serial number.

This parameter can be NULL if the serial number is not required.

This function returns the volume serial number that the operating system assigns when a hard disk is formatted. To programmatically obtain the hard disk's serial number that the manufacturer assigns, use the Windows Management Instrumentation (WMI) Win32_PhysicalMedia property SerialNumber.
Раз это возвращаемое число, значит out uint.

Цитата

lpMaximumComponentLength
A pointer to a variable that receives the maximum length, in TCHARs, of a file name component that a specified file system supports.

A file name component is the portion of a file name between backslashes.

The value that is stored in the variable that *lpMaximumComponentLength points to is used to indicate that a specified file system supports long names. For example, for a FAT file system that supports long names, the function stores the value 255, rather than the previous 8.3 indicator. Long names can also be supported on systems that use the NTFS file system.
Раз это указатель на массив чисел, значит и должен быть массив чисел [MarshalAs(UnmanagedType.LPArray, SizeConst=255)] out uint[].

Цитата

lpFileSystemFlags
A pointer to a variable that receives flags associated with the specified file system.
Раз это возвращаемое число, значит out uint.

P.S. Кстати, функция помечена как WINAPI, значит в DllImport ещё флажок добавить CallingConvention = CallingConvention.Winapi.
« Последнее редактирование: 15-01-2012 07:42 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #6 : 15-01-2012 09:31 » 

ну у меня не GetVolumeInformationByHandleW, а GetVolumeInformationW

вот, сделал по аналогии

Код:
namespace GetDriveSerialNumber
{
public partial class Form1:Form
{
public Form1()
{
InitializeComponent();
}



const int MAX_PATH=260;



[DllImport("Kernel32.dll"
,EntryPoint="GetVolumeInformationW"
,CallingConvention=CallingConvention.Winapi
,CharSet=CharSet.Unicode
)]
public static extern int GetVolumeInformationW
(
string lpRootPathName,

[MarshalAs(UnmanagedType.LPArray,SizeConst=MAX_PATH+1)] out char[] lpVolumeNameBuffer,
uint nVolumeNameSize,

out uint lpVolumeSerialNumber,
out uint lpMaximumComponentLength,
out uint lpFileSystemFlags,

[MarshalAs(UnmanagedType.LPArray,SizeConst=MAX_PATH+1)] out char[] lpFileSystemNameBuffer,
uint nFileSystemNameSize
);



[DllImport("Kernel32.dll"
,EntryPoint="GetLastError"
,CallingConvention=CallingConvention.Winapi
,CharSet=CharSet.Unicode
)]
public static extern uint GetLastError
(
);




private void but_getinfo_Click(object sender,EventArgs e)
{


string lpRootPathName          ="C:\\";

char[] lpVolumeNameBuffer;
uint   nVolumeNameSize         = MAX_PATH;

uint   lpVolumeSerialNumber    ;
uint   lpMaximumComponentLength;
uint   lpFileSystemFlags       ;

char[] lpFileSystemNameBuffer;
uint   nFileSystemNameSize     = MAX_PATH;

if(0!=GetVolumeInformationW
(
lpRootPathName          ,
out lpVolumeNameBuffer      ,
nVolumeNameSize         ,
out lpVolumeSerialNumber    ,
out lpMaximumComponentLength,
out lpFileSystemFlags       ,
out lpFileSystemNameBuffer  ,
nFileSystemNameSize

)
)
{
int iii=1;
}

uint err=GetLastError();
}
}
}

ругается теперь вот так:



Добавлено через 46 минут и 38 секунд:
кстати, вот нашёл класс для определения производителя и ещё некоторых параметров привода
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394346(v=vs.85).aspx

это, насколько я понял, библиотека WMI и для её использования нужно подключить следующие пространства

Код:
using System.Management;
using ROOT.CIMV2.Win32;

но пространство ROOT - неизвестно

* err1.gif (34.14 Кб - загружено 1788 раз.)
« Последнее редактирование: 17-01-2012 03:05 от Алексей1153++ » Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 15-01-2012 18:09 » 

Алексей1153++, строчки-то зачем в массивы? А MaximumComponentLength почему в массив не переделал?

Утомляешь невнимательностью.
« Последнее редактирование: 15-01-2012 18:12 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #8 : 15-01-2012 19:07 » 

Dimka, при чём тут невнимательность! Я и не понял, что их надо массивом, это же одинокое число типа DWORD. Я со строками пытался как раз как смассивами работать. Ну ладно, ок, вернул строки, для чисел сделал массивы на 1 элемент

Код:
[DllImport("Kernel32.dll"
,EntryPoint="GetVolumeInformationW"
,CallingConvention=CallingConvention.Winapi
,CharSet=CharSet.Unicode
)]
public static extern int GetVolumeInformationW
(
string lpRootPathName,

out string lpVolumeNameBuffer,
uint nVolumeNameSize,

[MarshalAs(UnmanagedType.LPArray,SizeConst=1)] out uint[] lpVolumeSerialNumber,
[MarshalAs(UnmanagedType.LPArray,SizeConst=1)] out uint[] lpMaximumComponentLength,
[MarshalAs(UnmanagedType.LPArray,SizeConst=1)] out uint[] lpFileSystemFlags,

out string lpFileSystemNameBuffer,
uint nFileSystemNameSize
);

и сообщение теперь показывается вот такое

* err1.gif (41.78 Кб - загружено 1668 раз.)
Записан

Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 15-01-2012 19:59 » 

Код: (C#)
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace Problem {

    class Program {

        const int MAX_PATH = 260;
        const int BufferSize = MAX_PATH + 1;

        [DllImport(
            "Kernel32.dll",
            EntryPoint = "GetVolumeInformationW",
            CallingConvention = CallingConvention.Winapi,
            CharSet = CharSet.Unicode
        )]
        static extern bool GetVolumeInformation(
            string lpRootPathName,
            StringBuilder lpVolumeNameBuffer,
            uint nVolumeNameSize,
            out uint lpVolumeSerialNumber,
            out uint lpMaximumComponentLength,
            out uint lpFileSystemFlags,
            StringBuilder lpFileSystemNameBuffer,
            uint nFileSystemNameSize
        );

        static void Main(string[] arguments) {
            StringBuilder volumeNameBuffer = new StringBuilder(Program.BufferSize);
            uint volumeSerialNumber;
            uint maximumComponentLength;
            uint fileSystemFlags;
            StringBuilder fileSystemNameBuffer = new StringBuilder(Program.BufferSize);
            if (
                GetVolumeInformation(
                    "C:\\",
                    volumeNameBuffer,
                    Program.BufferSize,
                    out volumeSerialNumber,
                    out maximumComponentLength,
                    out fileSystemFlags,
                    fileSystemNameBuffer,
                    Program.BufferSize
                )
            )
            {
                Console.WriteLine("Name:\t\t{0}", volumeNameBuffer);
                Console.WriteLine("\nSN:\t\t0x{0}", volumeSerialNumber.ToString("X"));
                Console.WriteLine("File name size:\t{0}", maximumComponentLength);
                Console.WriteLine("Flags:\t\t0x{0}", fileSystemFlags.ToString("X"));
                Console.WriteLine("File system:\t{0}", fileSystemNameBuffer);
            }
            else
            {
                Console.WriteLine("Fail.");
            }
            Console.ReadKey();
        }

    }

}
« Последнее редактирование: 15-01-2012 21:11 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #10 : 16-01-2012 03:29 » 

Dimka, во, спасибо! StringBuilder  - это то, чего не хватало, и никакого маршаллинга стало не надо ) 
Осталось ещё WMI победить как-то. Уж не буду тебя мучать, переключусь на Джона Ага

Добавлено через 5 часов, 11 минут и 26 секунд:
вот имеется такой код, который вроде то, что надо
Код:
using System.Management;

...

SelectQuery q = new SelectQuery("Win32_PhysicalMedia");
ManagementObjectSearcher s = new ManagementObjectSearcher(q);

StringBuilder sb = new StringBuilder();


foreach(ManagementObject drive in s.Get())
{
sb.Append(drive.Properties["SerialNumber"].Value);
sb.Append(drive.Properties["Manufacturer"].Value);
sb.Append("\r\n");
}

но с одной проблемой - к sb добавляются лишь пустые строки  , возвращаемые .Value  . Что тут не так ?
« Последнее редактирование: 16-01-2012 08:40 от Алексей1153 » Записан

zubr
Гость
« Ответ #11 : 16-01-2012 09:12 » 

Наверно так:
Код:
foreach(ManagementObject drive in s.Get())
{
sb.Append(drive["SerialNumber"]);
sb.Append(drive["Manufacturer"]);
sb.Append("\r\n");
}
Записан
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #12 : 16-01-2012 11:37 » 

zubr, нет, так тоже добавляются пустые строки
« Последнее редактирование: 16-01-2012 11:40 от Алексей1153++ » Записан

Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #13 : 16-01-2012 11:54 » 

Попробуй.

* Testhdd.zip (26.9 Кб - загружено 816 раз.)
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #14 : 16-01-2012 20:34 » new

Джон, спасибо, круто работает Улыбаюсь По аналогии вытащил нужный класс - Win32_CDROMDrive
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines