Perl for Win32 Frequently Asked Questions (FAQ)

Main Page

8. General programming

8.1. How do I change the Win32 registry?

There are several Win32 registry functions provided with Perl for Win32. Check the win32mod document provided with Perl for Win32.

If you don't understand how the registry works, remember that a *key* is like a directory, and a *value* is like a file. There are several *top*level*keys*, and these are kind of like drives.

If you really don't get the registry, it's probably in your best interest not to mess around with it.

8.2. How do I read from/write to a named pipe?

Named pipes are a inter-process communcations mechanism, mainly used with Microsoft operating systems (like Win32 platforms). A named pipe can be addressed just like a file.

The name of a named pipe is a UNC (Universal Naming Convention) name, and looks like "\\servername\pipe\pipename". "servername" is the name of the server you're connecting to, or "." for the current computer. "pipe" is a constant, and "pipename" is the name of the pipe, such as "sql" for Microsoft SQL Server.

You can use open(), close(), read(), and print() on a named pipe just like a file. However, you can't use sysread() or syswrite() on one, because they aren't really files.

There's a program called Win32Pipe on the CPAN archive that can be used to create a named pipe.

If you're starting from scratch, and you have a TCP/IP infrastructure, consider using sockets rather than named pipes for your IPC mechanism.

8.3. How do I write socket scripts?

There are several examples of socket scripts that are distributed with Perl for Win32. They're in the eg subdirectory of your perl directory.

See question 8.5, by the way, about sockets servers.

8.4. What's all this I hear about not being able to use a socket as a filehandle?

Early versions of Perl for Win32 didn't allow you to read or write to a socket as if it were a filehandle. The current versions fully support this, and you shouldn't worry about it too much. If the version that you're using doesn't work well, get the latest build from ActiveWare (see question 1.4).

Contrary the ActiveWare FAQ (see question 3.7), you don't have to specify USE_SOCKETS_AS_FILEHANDLES when building Perl for Win32 to get sockets to work like filehandles. It doesn't _hurt_, but it's not necessary.

8.5. How do I write a sockets server in Perl for Win32?

There's an example of a socket server, TCP-SERVER, in the eg directory of your perl directory. In general, information on socket programming for UNIX is applicable to Perl for Win32. See especially the perlipc page of the documentation.

Note that using Perl for Win32 is *not* a good way to implement a server, since you will only be able to service one client at once. This is because a) Perl, the language, doesn't support threads, and b) Perl for Win32 doesn't support the fork() function.

[Any new information here? -ESP]

8.6. How do I send or receive files by FTP?

There's an ftp.pl file in the lib directory of the perl subdirectory, but it doesn't work, since it depends on alarm() and select() calls that aren't available in Perl for Win32. Net::FTP, from the CPAN archive, also appears not to work. [Anyone have better information? -ESP]

Thus, you have several possibilities for doing FTP. You can fix the ftp.pl script so that it works for Perl for Win32 [If you do, please share it! -ESP]. You can get a copy of the FTP specification and hand- code the module from scratch.

The quick-and-dirty solution is to compile a script for the FTP program that comes with Windows NT [and Windows 95? -ESP]. You can then execute the FTP program, passing this script as a parameter. See the FTP program's help file for more details. Yes, I know, it's a real ugly solution, but it works.

Aldo Calpini has developed a Perl for Win32 extension to do FTP and HTTP using the WININET library. It's in alpha testing and is available on his web page (see question 3.4).

8.7. How do I send or receive files by HTTP?

Again, the CPAN solution would be to use libwww. However, to work under Perl for Win32, libwww must be altered. See the information at this URL:

http://www.its.unimelb.edu.au:801/hma/pub/libwww/d009/0028.html

The HTTP protocol is pretty simple, and throw-away solutions can be hand-coded pretty easily. See the HTTP protocol specification, and the sockets examples, as mentioned above.

Aldo Calpini has developed a Perl for Win32 extension to do FTP and HTTP using the WININET library. It's in alpha testing and is available on his web page (see question 3.4).

8.8. How do I manage user accounts with Perl for Win32?

There's an extension called Win32::NetAdmin distributed with Perl for Win32. It has a pretty low-level interface, but it is very possible to manage users and groups with this module.

8.9. How do I read from and write to serial ports?

Serial ports can be opened just like files in Perl for Win32. To open COM1, just do this:

    open( PORT, "+>COM1" ) or die "Can't open COM1: $!";

You should be able to read from and write to the file handle using the standard I/O functions (read() and print()), but not the system functions (sysread() and syswrite()). [Anyone done this? Does it really work? Caveats? -ESP]

It has been noted (but not tested) that modems that use the Hayes command set require a carriage return (\r) rather than a line feed (\n) at the end of the command.

8.10. Why doesn't the -d operator work?

It does, in fact, work. However, people tend to use it incorrectly and get bad results. To check for all the sub-directories in a directory, try code like this:

    $path = shift;
    $path = "." unless $path;

    opendir( DIR, $path )
      or die "Can't open $path: $!";

    while ( $entry = readdir( DIR ) )
    {
      $type = ( -d "$path\\$entry" ) ? "dir" : "file"; # $path is crucial!
  
      print "$type\t$entry\n";
    }

    closedir( DIR );

It's a common mistake to leave out the $path from the -d check. If you do this, perl thinks you're talking about files in the current directory. Since the dirs don't -e in your current directory, they definitely don't -d. Exceptions are "." and "..", which exist in every directory.

8.11. Reading from and writing to files mysteriously fails. What's wrong?

On Win32 platforms, there's a big difference between text files and binary files. For text files, the "\r\n" characters are translated into "\n" when read from disk, and the ^Z character is read as an end-of-file marker. For binary files, no such translation is used.

Although this works great for text files, it really messes things up when you're trying to read and write binary files. If the read or write does not abort prematurely because a ^Z was found in the file, you will almost definitely get incorrect bytes in the file due to \n -> \r\n translation.

The problem is that Perl for Win32, and the C runtime library it uses, open file in text mode by default. For each file handle you use in Perl for binary data, you need to specify that the file handle is in binary mode. Fortunately, there's a function, binmode, that does just that. See the perlfunc documentation file for details.

This script copies one binary file to another. Note its use of binmode to set the mode of the file handle.

    open( INFILE, "<$infile" );
    open( OUTFILE, ">$outfile" );

    binmode( INFILE ); binmode( OUTFILE ); # crucial for binary files!

    while ( read( INFILE, $buffer, 1024 ) )
    {
      print OUTFILE $buffer;
    }

    close( INFILE ); close( OUTFILE );

8.12. When I try to open a file, I get a "bad argument" error. What gives?

Win32 platforms use the '\' character as a delimiter for paths in a file name (C:\like\this). However, Perl uses the '\' character as an escape code, to symbolize a special character like the line feed character ("\n") or the tab character ("\t").

So, if you try and open a file like this:

    open( MYFILE, "C:\temp\newfile.txt" );

you'll get an error. One solution is to replace each '\' with a double-'\', to show that you really mean to use that character, not an escape:

    open( MYFILE, "C:\\temp\\newfile.txt" );

Another solution is to use non-interpolating single quote strings, which lets Perl know not to use any special characters:

    open( MYFILE, 'C:\temp\newfile.txt' );

See the perlop documentation page for more information on the differences between single quotes (') and double quotes (").

8.13. Why do I get an error using Perl's "here-doc" syntax (<<), that says "Can't find string terminator anywhere before EOF"?

This is a weird error that occurs when your string terminator is on the last line of your script. With a script like:

    print <<"END";
    The snake is old, and his skin is cold.
    END

perl is looking for the word "END" on a line by itself, followed by a line-feed character ("\n"). If the "END" is the last line of your script, you have to remember to hit <Enter> after the word "END", so that Perl can recognize it as the string terminator.

Most UNIX text editors will do this automatically. Most Windows text editors won't. Thus the problem.

Note that this can also cause a problem with Perl formats, since these are terminated with a single "." on a line by itself. However, it's much more rare, since programmers often specify the format for output at the top rather than at the bottom of a file.