Вы не можете сделать это с олицетворением, если учетная запись не может войти в систему. Для олицетворения требуется, чтобы поток запускался под учетными данными пользователя. Вот почему LogonUser
терпит неудачу.
Вы можете использовать функцию WNetAddConnection2 , которая используется для установления соединения с сетевым ресурсом.
Вот пример дляваша CreateDirectoryIfNotExist
функция, использующая этот подход:
public static void CreateDirectoryIfNotExists(string directory, string sharePath, string username, string password)
{
NETRESOURCE nr = new NETRESOURCE();
nr.dwType = ResourceType.RESOURCETYPE_DISK;
nr.lpLocalName = null;
nr.lpRemoteName = sharePath;
nr.lpProvider = null;
int result = WNetAddConnection2(nr, password, username, 0);
string directoryFullPath = Path.Combine(sharePath, directory);
if (!Directory.Exists(directoryFullPath))
{
Directory.CreateDirectory(directoryFullPath);
}
}
Чтобы сделать системный вызов, вам также понадобятся следующие определения из pinvoke.net .
[StructLayout(LayoutKind.Sequential)]
private class NETRESOURCE
{
public ResourceScope dwScope = 0;
public ResourceType dwType = 0;
public ResourceDisplayType dwDisplayType = 0;
public ResourceUsage dwUsage = 0;
[MarshalAs(UnmanagedType.LPStr)] public string lpLocalName = null;
[MarshalAs(UnmanagedType.LPStr)] public string lpRemoteName = null;
[MarshalAs(UnmanagedType.LPStr)] public string lpComment = null;
[MarshalAs(UnmanagedType.LPStr)] public string lpProvider;
};
public enum ResourceScope
{
RESOURCE_CONNECTED = 1,
RESOURCE_GLOBALNET,
RESOURCE_REMEMBERED,
RESOURCE_RECENT,
RESOURCE_CONTEXT
};
public enum ResourceType
{
RESOURCETYPE_ANY,
RESOURCETYPE_DISK,
RESOURCETYPE_PRINT,
RESOURCETYPE_RESERVED
};
public enum ResourceUsage
{
RESOURCEUSAGE_CONNECTABLE = 0x00000001,
RESOURCEUSAGE_CONTAINER = 0x00000002,
RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004,
RESOURCEUSAGE_SIBLING = 0x00000008,
RESOURCEUSAGE_ATTACHED = 0x00000010,
RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED),
};
public enum ResourceDisplayType
{
RESOURCEDISPLAYTYPE_GENERIC,
RESOURCEDISPLAYTYPE_DOMAIN,
RESOURCEDISPLAYTYPE_SERVER,
RESOURCEDISPLAYTYPE_SHARE,
RESOURCEDISPLAYTYPE_FILE,
RESOURCEDISPLAYTYPE_GROUP,
RESOURCEDISPLAYTYPE_NETWORK,
RESOURCEDISPLAYTYPE_ROOT,
RESOURCEDISPLAYTYPE_SHAREADMIN,
RESOURCEDISPLAYTYPE_DIRECTORY,
RESOURCEDISPLAYTYPE_TREE,
RESOURCEDISPLAYTYPE_NDSCONTAINER
};
public enum ResourceConnection
{
CONNECT_UPDATE_PROFILE = 1,
CONNECT_UPDATE_RECENT = 2,
CONNECT_TEMPORARY = 4,
CONNECT_INTERACTIVE = 8,
CONNECT_PROMPT = 0X10,
CONNECT_REDIRECT = 0X80,
CONNECT_CURRENT_MEDIA = 0X200,
CONNECT_COMMAND_LINE = 0X800,
CONNECT_CMD_SAVECRED = 0X1000,
CONNECT_CRED_RESET = 0X2000
};
[DllImport("mpr.dll", CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
private static extern int WNetAddConnection2(NETRESOURCE lpNetResource,
[MarshalAs(UnmanagedType.LPStr)] string lpPassword,
[MarshalAs(UnmanagedType.LPStr)] string lpUserName, int dwFlags);
Вы можете добавить это определение к тому же классу, что и ваша функция.
Здесь также приведены ссылки на два старых поста, в которых также используется тот же подход.
Доступ к общему файлу (UNC) из удаленного ненадежного домена с учетными данными
Как получить программный доступ к общей папке