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

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

Hi Monks.

I need to check connection to a particular Windows Share using the windows Net Use command.The output of Net use command is as follows:

New connections will be remembered. Status Local Remote Network ---------------------------------------------------------------------- +--------- OK \\10.81.253.70\G$ Microsoft Windows Net +work Disconnected \\10.81.253.140\IPC$ Microsoft Windows Net +work The command completed successfully.

Now to check connection for IP \\10.81.253.70\G$ , I wrote the following code

$inputDirectory="\\\\10.81.253.70\\G\$"; my $c = `net use`; my $unc = 0; my $h; my @a=split(' ',$c); foreach $h (@a) { if ($h eq 'OK' || $h eq 'Disconnected') { $status =$h; $temp=1; } elsif($temp == 1) { my $remote=$h; if($status eq 'OK' && $remote eq $inputDirectory) { $unc=1; } $temp = 0; } } if ($unc == 1) { print "UNC is Connected"; } else { print "UNC is Disconnected"; }

This works fine BUT if the share name is "\\10.81.253.70\file data\query files" than is fails because i am splitting the output of net use command on every space encountered so if the given share name contains spaces in its name than it breakes the share name on spaces , thus defeating my purpose. Please provide some help or tell how can i check connectivity to shares in windows through perl?

Replies are listed 'Best First'.
Re: Windows Net Use
by hdb (Monsignor) on Mar 28, 2013 at 08:15 UTC

    You can avoid splitting alltogether if you search for your share in the output of net use and then return the first word of that line.

    use strict; my $inputDirectory = '"\\\\10.81.253.70\\file data\\query files"'; # need to dublicate each \ in string $inputDirectory =~ s|\\|\\\\|g; my @lines = `net use`; foreach my $line ( @lines ) { next unless $line =~ m|$inputDirectory|; $line =~ /(^\S+)/; print $1; }

    This also overcomes the issue that the output of net use is sometimes split into two lines when it is too long. The output of net use sometime returns no status as well, which might be a problem or not.

      Thnks hdb .. But when i input the directory as

      my $inputDirectory = "\\\\10.81.253.140\\IPC\$";

      It does not return anything. Why??

        You found a material gap in my code. Problem is the escaped $ at the end. The backslash in front of it will be doubly escaped and then the $ will cause trouble.

        use strict; my $inputDirectory = '\\\\10.81.253.140\\IPC$'; # need to dublicate each \ in string $inputDirectory =~ s|\\|\\\\|g; $inputDirectory =~ s|\$|\\x{24}|g; # replace $ with hex representatio +n my @lines = `net use`; foreach my $line ( @lines ) { next unless $line =~ m|$inputDirectory|; $line =~ /(^\S+)/; print $1; }
        \\\\10.81.253.140\\IPC\$
        \\\\10.81.253.140\\IPC$   
        
Re: Windows Net Use
by soonix (Canon) on Mar 28, 2013 at 10:14 UTC

    The output of "net use" is generally bad to parse. If your Windos is new enough (XP Pro) to include WMIC, the output of

    WMIC NETUSE LIST FULL /FORMAT:CSV
    should contain all that you need, and is much easier to parse. Only problem would be share names with commas in them, but for a reason unbeknownst to me, these are much rarer than those with embedded spaces :-)

    There are several such command line utilities whose output is inconsistent or not parseable without mind reading capabilities. In such cases one should look for alternative sources of input.

      Parsing the output of WMIC looks even more difficult , cause its output is very different as compared to net use. So If u could tell me how to parse it or break it into what i need, it would be a great help..

        The suggested code will return the information in CSV format. Save it to a file and use something like Text::CSV to read only the columns you want.

        Update: use something like /output:c:\netuselist.csv to save the file.

        For the human eye it looks more gibberish, but for parsing it is less error prone.

        As marto already pointed out, the best solution is Text::CSV. Since CSV means "comma separated values", the second best is splitting on the commas.

        The first line that WMIC outputs, BTW, contains the field names.

Re: Windows Net Use
by Anonymous Monk on Mar 28, 2013 at 07:40 UTC
    try split /\s\s\s+/
Win32::FileOp instead of netuse
by ggoebel (Sexton) on Mar 28, 2013 at 20:50 UTC

    Way back... I would have used Win32::lanman. But apparently that module has fallen by the wayside. Looks like Jenda is now maintaining Win32::FileOp though.

    While it doesn't have all the knobs and buttons, it may be close enough. It won't show you disconnected or unavailable mappings... just the ones which are currently connected.

    use strict; use warnings; use Win32::FileOp; my %drive = Mapped or die $^E; for my $key (sort keys %drive) { print "$key = $drive{$key}\n"; } 1; __END__

      This does not seem to be working, it shows the following message even when i have connected ip using NET USE:

      This network connection does not exist at net-view.pl line 5.

        Can you post your code? It would help to see which line the error message is associated with.

        When I cut and paste my code snippet into a script and execute it, I get:

        c:\pub>mapped.pl
        E => \\spsrv_print\e
        
        c:\pub\>
        

        ...this is with Strawberry Perl 5.16.2 on Win7x64.

Re: Windows Net Use
by Anonymous Monk on Oct 02, 2014 at 17:58 UTC

    here is a kind of quick and dirty utility to use the WMIC NETUSE command to do things. not meant to be pretty - just present the data.

    use strict; my %netuse_from_wmic; my @wmic_output=`WMIC NETUSE LIST FULL /FORMAT:CSV`; my @title_data; my $LocalNameIndex; foreach my $wmic_line (@wmic_output) { chomp $wmic_line; $wmic_line=~s/\r$//; next if $wmic_line eq ""; if(0==scalar @title_data) { @title_data=split /,/,$wmic_line; for(my $idx=0;$idx<scalar @title_data;$idx++) { print "$idx=$title_data[$idx]\n"; $LocalNameIndex=$idx if $title_data[$idx]=~/^LocalName$/i; } die "no LocalName found in title" if !defined $LocalNameIndex; } else { my @wmic_netuse_entry=split /,/,$wmic_line; for(my $idx=0;$idx<scalar @title_data;$idx++) { $netuse_from_wmic{uc $wmic_netuse_entry[$LocalNameIndex]}{ +$title_data[$idx]}=$wmic_netuse_entry[$idx]; } } } foreach my $drive (sort keys %netuse_from_wmic) { print "Drive: $drive\n"; foreach my $value (sort keys %{$netuse_from_wmic{$drive}}) { print " $value=$netuse_from_wmic{$drive}{$value}\n"; } }