Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Copying files to an authenticated Win32 share

by grinder (Bishop)
on Sep 13, 2005 at 09:54 UTC ( #491533=sourcecode: print w/replies, xml ) Need Help??
Category: Win32 Stuff
Author/Contact Info grinder on perlmonks

I need to transfer files from one Windows machine to another. I've always needed to one way or another, over the years, and have always hacked up fragile workarounds, usuall involving batch files, "RunAs" commands, shares using hard-coded drive letters and so on.

All the pieces are already bundled with the Perl distribution, it was just a question of putting them together. This code, then, lays down an approach to the problem in a Perl-only manner.

# copy files to a remote share requiring authentication
# This program demonstrates how to find a free drive letter
# on the local machine, setting up the shared connection,
# copying the file over and then tearing down the connection
# afterwards. I hope this helps someone else save the two hours
# it took me to gather all the loose ends together.
# copyright (c) David Landgren 2005
# This program is free software; you can redistribute it and/or
# modify it under the same terms as Perl itself.

use strict;
use warnings;

use Win32::NetResource qw/GetUNCName AddConnection CancelConnection/;
use Win32API::File qw/ CopyFile fileLastError /;

use constant SHARE_NAME => '\\\\remote_svr\\sharename'; # must use bac
use constant USER_NAME  => 'myusername';
use constant PASSWORD   => 'mysekretpassword';

my $drive;
for my $letter ('g' .. 'z' ) {
    my $mapped;
    $drive = "$letter:";
    GetUNCName( $mapped, $drive );
    last if not $mapped;

my $share = {
    RemoteName => SHARE_NAME,
    LocalName  => $drive,

print "connecting $share->{RemoteName} to $share->{LocalName}\n";
if( not AddConnection( $share, PASSWORD, USER_NAME, 0 )) {
    die "connection error:\n", win32err();

for my $file( @ARGV ) {
    print "copying $file\n";
    CopyFile( $file, "$share->{LocalName}$file", 0 )
        or print "\tfailed: " . fileLastError() . "\n";

if( not CancelConnection( $share->{LocalName}, 0, 1 )) {
    print "disconnection error:\n", win32err();

sub win32err {
    my $err;
    # Win32::GetError($err); -- bug spotted by puploki
Replies are listed 'Best First'.
Re: Copying files to an authenticated Win32 share
by puploki (Hermit) on Sep 13, 2005 at 13:07 UTC
    Very neat, I always like pure Perl ways of doing stuff. A couple of thoughts:
    • If you don't have a Windows domain (i.e. have a set of disparate boxes in workgroups) then you would need to specify a valid account on the remote machine in the form "remotemachinename\\username".
    • When I ran your code on my machine, I got the following error:
      connecting \\server\share to g: Undefined subroutine &Win32::GetError called at line 54.
      But that could just be me missing something...
    • I'm also a bit twitchy about leaving a password in clear text lying around, but that's just me :)
Re: Copying files to an authenticated Win32 share
by SheridanCat (Pilgrim) on Sep 13, 2005 at 16:32 UTC
    Since you can map UNC pathnames "anonymously", there's really no reason to find a free drive letter. I use the following in a library I wrote:
    sub connect{ my ( $paths, $user, $password, $verbose ) = @_; # Make $paths an array reference, even if it isn't already if ( ref $paths ne "ARRAY") { if( ! ref $paths ){ push my @paths, $paths; $paths = \@paths; }else{ die "You must pass a scalar or array in as first argument +to connect()\n"; } } if( $^O eq 'MSWin32' ){ require Win32::NetResource qw( :DEFAULT GetSharedResources Get +Error AddConnection CancelConnection ); foreach my $path ( @$paths ){ # In case we don't have the leading backslashes, # add them. unless( $path =~ m|^\\{4}| ){ $path =~ s/^\\+//; $path = "\\\\" . $path; } my %resources = ( Scope => RESOURCE_GLOBALNET, Type => RESOURCETYPE_DISK, DisplayType => RESOURCEDISPLAYTYPE_SHARE, RemoteName => $path ); AddConnection( \%resources, $password, $user, 1 ); if( $verbose ){ my $err; GetError( $err ); warn Win32::FormatMessage( $err ); } } }else{ die "Unsupported Operating System: $^O\n"; } }

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: sourcecode [id://491533]
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (7)
As of 2023-12-10 13:52 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (40 votes). Check out past polls.