|
I also needed a way to find the next open drive. Here is what I came up with. Also included is a function to list current usage of network drives.
Private Const NO_ERROR As Int32 = 0
Private Const ERROR_NOT_CONNECTED As Int32 = 2250I
'Drive Types
Private Const DRIVE_UNKNOWN As Int32 = 0
Private Const DRIVE_NO_ROOT_DIR As Int32 = 1
Private Const DRIVE_REMOVABLE As Int32 = 2
Private Const DRIVE_FIXED As Int32 = 3
Private Const DRIVE_REMOTE As Int32 = 4
Private Const DRIVE_CDROM As Int32 = 5
Private Const DRIVE_RAMDISK As Int32 = 6
<dllimport("kernel32.dll", setlasterror:="True)"> _
Private Shared Function GetDriveType(ByVal strDrive As String) As Int32
End Function
<dllimport("mpr.dll", setlasterror:="True)"> _
Private Shared Function WNetGetConnection(ByVal strLocalName As String, _
ByVal sbRemoteName As StringBuilder, ByRef intLength As Int32) As Int32
End Function
Public Function GetNextAvailableDrive(ByRef strDriveLetter As String) As Boolean
Dim intStartLetter As Integer = Asc("A")
Dim intEndLetter As Integer = Asc("Z")
Dim intDriveType As Integer = 0
Dim blnDriveAvailable As Boolean
Dim strShareName As String = ""
Dim blnOpenDriveFound As Boolean = False
For intDriveLetter As Integer = intStartLetter To intEndLetter
strDriveLetter = Chr(intDriveLetter) & ":"
intDriveType = GetDriveType(strDriveLetter & "\")
If intDriveType = DRIVE_NO_ROOT_DIR OrElse intDriveType = DRIVE_REMOTE Then
blnDriveAvailable = DriveIsAvailable(strDriveLetter, strShareName)
If blnDriveAvailable Then
blnOpenDriveFound = True
Exit For
End If
End If
Next
If blnOpenDriveFound = False Then
strDriveLetter = Nothing
End If
Return blnOpenDriveFound
End Function
Private Function DriveIsAvailable(ByVal strDriveLetter As String, ByRef strShareName As String) As Boolean
Const MAX_PATH As Int32 = 260
Dim sbShareNm As New StringBuilder(MAX_PATH)
Dim intLength As Int32 = MAX_PATH
Dim intReturnCode As Integer = 0
intReturnCode = WNetGetConnection(strDriveLetter, sbShareNm, intLength)
If intReturnCode = NO_ERROR Then
strShareName = sbShareNm.ToString
Return False
ElseIf intReturnCode = ERROR_NOT_CONNECTED Then
Return True
Else
Throw New System.ComponentModel.Win32Exception(intReturnCode)
End If
End Function
Private Function GetAllDrivesInfo() As NameValueCollection
Dim intStartLetter As Integer = Asc("A")
Dim intEndLetter As Integer = Asc("Z")
Dim intDriveType As Integer = 0
Dim blnDriveAvailable As Boolean
Dim strDriveLetter As String = ""
Dim strShareName As String = ""
Dim colDriveInfo As New NameValueCollection
For intDriveLetter As Integer = intStartLetter To intEndLetter
strDriveLetter = Chr(intDriveLetter) & ":"
intDriveType = GetDriveType(strDriveLetter & "\")
Select Case intDriveType
Case DRIVE_UNKNOWN, DRIVE_REMOVABLE, DRIVE_FIXED, DRIVE_CDROM, DRIVE_RAMDISK
colDriveInfo.Add(strDriveLetter, "")
Case DRIVE_NO_ROOT_DIR, DRIVE_REMOTE
blnDriveAvailable = DriveIsAvailable(strDriveLetter, strShareName)
If blnDriveAvailable Then
colDriveInfo.Add(strDriveLetter, "")
Else
colDriveInfo.Add(strDriveLetter, strShareName)
End If
End Select
Next
Return colDriveInfo
End Function
|
|
|
|
|
Hello there!
First of all, thanks for the article. It solved one big problem I was facing.
Now, it's my time to contribute with it...
According to Miscrosoft, we can have connection without the localname. You connection code works just fine with it, however, it fails on the disconnect. According to the documentation at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wnet/wnet/wnetcancelconnection2.asp,
we can replace the localname with the path connected.
I have changed it and this is working just fine with me. I'm posting it
private void zUnMapDrive(bool pfForce)
{
//call unmap and return
int iFlags=0;
if(lf_Persistent){iFlags+=CONNECT_UPDATE_PROFILE;}
int i = WNetCancelConnection2A(ls_Drive, iFlags, Convert.ToInt32(pfForce));
if (i != 0)
i = WNetCancelConnection2A(ls_ShareName, iFlags, Convert.ToInt32(pfForce));
if(i>0){throw new System.ComponentModel.Win32Exception(i);}
}
Hope this helps someone.
Regards,
Joao
|
|
|
|
|
Hello , Thanks for that, I have updated my source and will post an update to CodeProject before long (it will be build 0016). I have made a note of your contribution in the source, but since I dont have your name, its credited to jsantos98
----------------------------
Adam Woods
|
|
|
|
|
Hello Adam,
Thanks for the credit.
My name is "Joao Santos"
Regards,
Joao
|
|
|
|
|
Hi there, this hasn't workd for me. I fetched the code from your homepage. Ran the solution directly, tried mapping with no drive letter (which worked) and then unmapping which didn't work.
tried different servers, including windows 2003 and no luck.
|
|
|
|
|
Sorry for that. The interface has a minor bug
missing the line
oNetDrive.ShareName = txtAddress.Text;
in the button4_Click - disconnect event.
after realizing that, it works fine.
Allegro
|
|
|
|
|
I had this same issue, except mine was not working when passing share name for WNetCancelConnection2. I changed it to pass the local drive and it worked fine. I am testing in win2003 and xp.
In function unMapDrive():
iRet = WNetCancelConnection2(_localDrive, iFlags, System.Convert.ToInt32(_force));
Hope this helps anyone who may have had my same issue.
|
|
|
|
|
Thanks for posting this. It works where some other code fails. This code allows the DOMAIN to be supplied in the logon credential details allowing cross domain drive mapping.
ps. I was intested how this class worked
|
|
|
|
|
Hi I was trying to use this class, after some experimentation on my own I was able to figure out how it works but I then tried your class and i'm running into the same problem. It always returns the following error message:
An exception occurred while connecting: System.ComponentModel.Win32Exception: Th
e network name cannot be found
at aejw.Network.NetworkDrive.zMapDrive(String psUsername, String psPassword)
in c:\Documents and Settings\jmarshall\My Documents\SharpDevelop Projects\EventA
rchiver\cNetworkDrives0015.cs:line 173
at aejw.Network.NetworkDrive.MapDrive(String Username, String Password) in c:
\Documents and Settings\jmarshall\My Documents\SharpDevelop Projects\EventArchiv
er\cNetworkDrives0015.cs:line 129
at EventArchiver.MainClass.Main(String[] args) in c:\Documents and Settings\j
marshall\My Documents\SharpDevelop Projects\EventArchiver\Main.cs:line 80
Any idea whats going on?
ps. the reason it is under this post isntead of new thread is the new thread button doesn't seem to be working for me.
Thanks!
|
|
|
|
|
Sorry for the really slow reply, I only just noticed your post, I only get notified of new threads.
I would say you are not setting the "ShareName" property.
eg.
oNetDrive.ShareName = "\\ComputerName\Share1"
----------------------------
Adam Woods
|
|
|
|
|
Is there any chance you could update the code to allow mapping to an IPC$ share? You example forces you to map to a drive letter which is what I'm trying not to do. I need to map to something like: \\servername\ipc$. I suppose what I really looking for is the .Net equivalent of the "new use" command.
|
|
|
|
|
This looks like it'll do the trick. I'll update in the morning after I've had the chance to test across the network in different domains.
|
|
|
|
|
Sorry I don't see the code regarding ipc$. Could you repost it?
Thanks
|
|
|
|
|
I've seen many message board posters wanting to know how to map drives using .NET, so I know this will come in handy for a lot of people, but where is the artcle? All you seem to show is how to use your component, not how it was built.
I believe your ultimate rating will end up quite a bit higher if you take us through the process of writing the code and explaining how you did it. That's one of the things that makes The Code Project so popular. There are endles places to downlowd useful components. Folks come here to learn.
Charlie
if(!curlies){ return; }
|
|
|
|
|
the same way as "old" language does using API
Regards,
unruledboy@hotmail.com
|
|
|
|
|
Well, yes, but how you specifically did it is not what I'm getting at. The learning comes when you show your process, not just how to use the finished product.
Charlie
if(!curlies){ return; }
|
|
|
|
|
I agree. Not to denigrate the author, but it would be better to write about what the code does than how to use it (which should be obvious from the function signatures and in code documentation.
|
|
|
|
|
Who cares how the code works!!! as long as you got the class, and a description about the methods in the class. Why would you want to know how the code works... isn't that the whole point of OO programming.
Brendan
|
|
|
|
|
Because this site is intended to contain articles; It's not intended to be just a code-dump. It's perfectly fine if you just want to use the component and don't care how it works, but explaining how the component was built adds quite a bit of value to the article.
Charlie
if(!curlies){ return; }
|
|
|
|