I liked Mark Brackett's answer so much that I did my own quick implementation. Here it is if anyone else needs it in a hurry:
public class NetworkConnection : IDisposable
{
string _networkName;
public NetworkConnection(string networkName,
NetworkCredential credentials)
{
_networkName = networkName;
var netResource = new NetResource()
{
Scope = ResourceScope.GlobalNetwork,
ResourceType = ResourceType.Disk,
DisplayType = ResourceDisplaytype.Share,
RemoteName = networkName
};
var userName = string.IsNullOrEmpty(credentials.Domain)
? credentials.UserName
: string.Format(@"{0}\{1}", credentials.Domain, credentials.UserName);
var result = WNetAddConnection2(
netResource,
credentials.Password,
userName,
0);
if (result != 0)
{
throw new Win32Exception(result);
}
}
~NetworkConnection()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
WNetCancelConnection2(_networkName, 0, true);
}
[DllImport("mpr.dll")]
private static extern int WNetAddConnection2(NetResource netResource,
string password, string username, int flags);
[DllImport("mpr.dll")]
private static extern int WNetCancelConnection2(string name, int flags,
bool force);
}
[StructLayout(LayoutKind.Sequential)]
public class NetResource
{
public ResourceScope Scope;
public ResourceType ResourceType;
public ResourceDisplaytype DisplayType;
public int Usage;
public string LocalName;
public string RemoteName;
public string Comment;
public string Provider;
}
public enum ResourceScope : int
{
Connected = 1,
GlobalNetwork,
Remembered,
Recent,
Context
};
public enum ResourceType : int
{
Any = 0,
Disk = 1,
Print = 2,
Reserved = 8,
}
public enum ResourceDisplaytype : int
{
Generic = 0x0,
Domain = 0x01,
Server = 0x02,
Share = 0x03,
File = 0x04,
Group = 0x05,
Network = 0x06,
Root = 0x07,
Shareadmin = 0x08,
Directory = 0x09,
Tree = 0x0a,
Ndscontainer = 0x0b
}
Best Answer
We experienced this as well, and while I can't tell you WHY our resolution worked, i can tell you WHAT worked.
Map the drive in the code. Don't rely on the drive being mapped just because you're using the same account.
Based on the behavior we saw, this is what i would GUESS was happening in our situation and what's happening in yours.
The service we had issues with used a drive that was mapped in a login script. If we had the machine logged in as the same user the service was using, it worked, but if not it wouldn't work. Based on that, I surmised that the drive simply isn't mapped because the service doesn't really "log on".
Mapping the drive in code fixed it.
As a side note, you can also reference the UNC path directly, but we had permissions issues with that as well. Mapping the drive, passing in a username and password worked much better for us.
Our code for doing this:
Using the above class, you can map and disconnect the drive at will. If this is a service, I would recommend mapping the drive just before you need it and disconnecting the drive immediately after you need it.