http://www.perlmonks.org?node_id=676238

perlofwisdom has asked for the wisdom of the Perl Monks concerning the following question:

I have a need to connect to the C$ and D$ shares on various windows servers. I want to loop through the servers one at a time, and re-use the same local drive letter for the share. I'm having trouble getting the disconnect subroutine to delete the share before it tries to connect to the next server.

I am using the following command to make the connection (this works OK):

   system("net use ${drive} \\\\${server}\\${remote_drv_ltr}\$ ${passwd} /USER:${domain}\\${login}");

I cobbled together an 'unmount' routine to disconnect the share before going on to the next server. Retrying the delete command every 2 seconds for up to 30 seconds before giving up (this doesn't work reliably).

while ( system("net use $drive /DELETE") ) { : (I can provide the details if necessary) }

I've fumbled around with Win32::NetResource but can't find a good example of how to get it to map a drive, and later release it. Here's what I've got (which doesn't work at all):

use Win32::NetResource qw(:DEFAULT GetSharedResources GetError AddCo +nnection CancelConnection); my $Domain = 'aaaaaaaa'; my $Account = 'bbbbbbbb'; my $Password = 'cccccccc'; my $Server = 'dddddddd'; my $LocalDrive = 'X:'; my $UserName = '${Domain}\\${Account}'; my $Connection = 0; my $ShareInfo = { 'path' => "C:\\temp", 'netname' => "MyShare", 'remark' => "It is good to share", 'passwd' => "", 'current-users'=> 0, 'permissions' => 0, 'maxusers' => -1, 'type' => 0, }; my %NETRESOURCE = ( 'Scope' => 'RESOURCE_REMEMBERED', 'Type' => 'RESOURCETYPE_DISK', 'DisplayType' => 'RESOURCEDISPLAYTYPE_SHARE', 'Usage' => 'RESOURCEUSAGE_CONTAINER', 'LocalName' => "$LocalDrive", 'RemoteName' => "\\\\$Server\\D\$", 'Provider' => "$Server" ); AddConnection(\%NETRESOURCE,$Password,$UserName,$Connection); # CancelConnection($Name,$Connection,$Force);

I'm sure I'm way off (as evidenced by my lack of results). Do any of you have any constructive suggestions, alternate solutions, or (preferably) some sample code to help me get Win32::NetResource's "AddConnection" and "CancelConnection" to do what I need?

Replies are listed 'Best First'.
Re: How do you Map & Disconnect Network Drives (in Windows)?
by igelkott (Priest) on Mar 25, 2008 at 21:07 UTC

    Two suggestions from the system side (not Perl):

    • check the persistent flag in net use
    • use mountvol as a diagnostic tool to check if your unmapped drive really has been deleted or is still hanging around

    I've always found drive mapping a bit unreliable in Windows so my suggestions may not be the best available.

      I have seen the enemy, and the enemy is me (as usual). Your tip on the "persistent" flag led me down a path to the solution.

      The problem with the disconnect was that I had done a 'chdir' into the share after mounting it. And, since I was still sitting in the directory when I went to unmount it, it wouldn't release the mapping to the drive. As always thank you everyone for your input, I have learned much today that I will use again tomorrow!

Re: How do you Map & Disconnect Network Drives (in Windows)?
by Corion (Patriarch) on Mar 26, 2008 at 07:04 UTC

    Do you need to map the shares to drive letters at all? You can access files on the shares directly by using their UNC names:

    my $server = "\\\\$machine\\C\$"; my $fullname = "$server\\some\\file"; open my $fh, "<", $fullname or die "Couldn't open '$fullname': $!";
      Thank you for the suggestion (and the code snippet), that would solve all sorts of problems. Unfortunately, I hit an "Access denied" issue (which is a whole other problem). It's curious though because when I "map" the drive, I have full rights.

        The file access runs as the current user with the permissions of the current user. If you want to do the access with the credentials of a different user, you will either have to use the impersonation APIs or map the network drive.

Re: How do you Map & Disconnect Network Drives (in Windows)?
by Jenda (Abbot) on Mar 26, 2008 at 07:09 UTC

    The RESOURCE_REMEMBERED, RESOURCETYPE_DISK, etc. is NOT supposed to be a string! It's a constant, so drop the singlequotes. There's also no point in putting doublequotes aroung variables, this is Perl, not shell! So 'LocalName'    =>  $LocalDrive, not 'LocalName'    =>  "$LocalDrive",. On the other hand, if you use singlequotes, then variables are not interpolated into strings, try to print the $UserName !!!

    You might want to have a look at Win32::FileOp. I think it has a more Perlish interface.

      I've dropped the unnecessary quotes as you suggested. I have a really stupid question though: where do these constants derive their values? I wanted to see what their values were, so I printed them out, and got this:
      key DisplayType=3 key Scope=3 key Type=1 key Usage=2
      I had a look at the FileOp module, and it looks like it would do just what I need. Unfortunately, it takes an act of congress to deploy a module that isn't part of the standard install around here -- so I'll get the paperwork started. By the way didn't you write FileOp?

        Yes, I did write Win32::FileOp :-)

        The constants are defined within Win32::NetResource. They are defined in the XS (C with some Perl-specific macros) part of the module. And originaly they are defined by Microsoft somewhere in their C header files.