WNetAddConnection2 возвращает ошибку 1200 - действительное локальное имя
Я пытаюсь подключить общий ресурс (скажем, \server\folder) к моему локальному устройству X:
[DllImport("Mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int WNetAddConnection2(
[In] NetResource lpNetResource,
string lpPassword,
string lpUsername,
int flags
);
public static bool Connect(string remoteName, string localName, bool persistent) {
if (!IsLocalPathValid(localName)) return false;
var r = new NetResource
{
dwScope = ResourceScope.RESOURCE_GLOBALNET,
dwType = ResourceType.RESOURCETYPE_ANY,
dwDisplayType = ResourceDisplayType.RESOURCEDISPLAYTYPE_SHARE,
dwUsage = ResourceUsage.RESOURCEUSAGE_CONNECTABLE,
lpRemoteName = remoteName,
lpLocalName = localName
};
return WNetAddConnection2(r, null, null, persistent ? 1 : 0) == 0;
}
[StructLayout(LayoutKind.Sequential)]
public class NetResource {
public ResourceScope dwScope;
public ResourceType dwType;
public ResourceDisplayType dwDisplayType;
public ResourceUsage dwUsage;
public string lpLocalName;
public string lpRemoteName;
public string lpComment;
public string lpProvider;
}
При звонке
Connect(@"\\server\folder", "X:", true);
функция просто возвращает false - ошибка говорит 1200 (BAD_DEVICE).NETResource выглядит так:
lpRemoteName = "\\\\server\\folder";
lpProvider = null;
lpLocalName = "X:";
lpComment = null;
dwUsage = Connectable;
dwType = Any;
dwScope = GlobalNet;
dwDisplayType = Share;
Я уже проверил несколько фрагментов (PInvoke), я не вижу никакой разницы. Может быть, вы можете решить эту загадку...
EDIT1
2 ответа
[StructLayout(LayoutKind.Sequential)]
Вот где проблема началась, атрибут не указывает CharSet
имущество. По умолчанию используется CharSet.Ansi, изумительный выбор, для которого требуется отключение на машине времени, возвращающее вас назад к 1998 году. Таким образом, код передает структуру со строками, которые переводятся в 8-битные символы, в функцию, которая является явно использует Unicode-вариант функции. Неизбежно реализация видит мусор.
Вы можете форсировать маршалинг каждого отдельного члена строки с помощью [MarshalAs]. Но просто и логично сделать совпадение типов символов. Fix:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
Я наконец сделал это.
Я решил проблему, добавив
[MarshalAs(UnmanagedType.LPWStr)]
Атрибут каждого строкового поля внутри моего класса NetResource. К сожалению, я не знаю, почему это решает проблему...