DailyJS

DailyJS

The JavaScript blog.


Tagwindows-and-node
Featured

tutorials node windows windows-and-node

Windows and Node: PowerShell

Posted on .

To read previous posts in this series, view the windows-and-node tag.

This article is aimed at Unix-oriented developers who are interested in learning a little bit about Windows scripting. It also demonstrates an easy way of calling PowerShell from Node.

Windows PowerShell is comprised of three parts: a command-line shell, a scripting language, and an integration layer with the .NET Framework. It supports both COM and WMI, so combined with the scripting facilities it's a perfect tool for administrative task automation. There are quite a few Node modules that include shell scripts -- PowerShell is a Windows-friendly way of achieving similar goals.

Modules that include man pages for Unix systems can support Windows by including Windows PowerShell Help, which are essentially just XML files. I'm not sure if it's sensible to use this to document a Node program because it seems focused on PowerShell modules themselves, but it seems worth mentioning.

If you're a Unix-based Node developer who's looking to support Windows users, then it's a good idea to familiarise yourself with the basics of PowerShell. PowerShell can be used to execute programs, which will run as a separate process (just like a Unix shell). .NET programs designed specifically for PowerShell are called cmdlets -- these are considered "native" commands and execute within the current PowerShell process. They can actually support input and output as objects, which means collections of objects like arrays can be read and written using pipes.

Using PowerShell

Loading PowerShell

The Windows PowerShell binary itself can be found in the Start menu under All Programs, Accessories. There's also Windows PowerShell ISE (Integrated Scripting Environment), which is an IDE for writing PowerShell scripts.

Once it's loaded, you can try issuing some commands. The help pages I mentioned can be accessed with get-help, so try typing get-help get-service:

Loading PowerShell

Tab completion is supported, so typing Get- and pressing tab will cycle through each matching command. Completion also works for parameters.

PowerShell also features aliases to Unix commands. The Get-ChildItem cmdlet lists files and directories, much like ls in Unix. Fortunately, Get-ChildItem is aliased to ls, which makes things a little bit easier for those versed in Unix shells. There are lots of other aliases for DOS and Unix commands:

  • Get-Content: cat
  • Get-Help: man, help
  • Set-Location: cd

Using PowerShell with Node

What I've been building to here is how to take advantage of PowerShell's convenience and integration with Window-specific APIs and interfaces like COM from within Node programs. This program will list the current directory using Node's child_process module:

var exec = require('child_process').exec;

// List a directory
exec('powershell.exe -Command "Get-ChildItem"', function(err, stdout, stderr) {  
  console.log(stdout);
})
.stdin.end();

The basic pattern is powershell.exe -Command "...". The result should look like this:

PowerShell from Node

Meanwhile, accessing objects using COM is also supported by PowerShell:

var exec = require('child_process').exec  
  , script;

// Use COM objects to get filesystem information
script = '$f = new-object -com "scripting.filesystemobject"; $f.drives | where {$_.drivetype -eq 2} | Select Path,AvailableSpace,FreeSpace,TotalSize';

exec('powershell.exe -Command "' + script + '"', function(err, stdout, stderr) {  
  console.log(stdout);
})
.stdin.end();

Where might this come in useful? Well, I have a feeling that certain modules that depend on Unix-specific binaries could be ported to Windows more easily by using PowerShell. And Windows developers could use it to interface with native services without building native addons.

Summary

  • PowerShell is a command-line shell, scripting language, and integration layer with .NET
  • It supports help files and is extensible
  • Commands often work with objects rather than text, and objects can be pipelined
  • Forking using the PowerShell binary is possible, which may help port modules that depend on Unix binaries

Featured

tutorials node logging windows windows-and-node

Windows and Node: Event Logs

Posted on .

To read previous posts in this series, view the windows-and-node tag.

Windows has event logs with three categories: System, Application, and Security. These are known as "sources" in Windows terminology, and since NT 4.0 it's been possible to create custom sources as well. Pretty much every version of Windows I've ever seen has included an Event Viewer utility, which can be used to view and manipulate logs.

Event logs are useful in Windows for the same reasons as syslog in Unix. Logging messages from background services is one of the most obvious examples, particularly as Node seems like a promising platform for developing Windows services.

In Node this requires an addon, because native bindings are needed to communicate with the eventlog service. Windows Event Log Js (GitHub: jfromaniello / windowseventlogjs, License: MIT, npm: windows-eventlog) by José F. Romaniello is one such addon.

On a related note, José has also written a great tutorial on how to create Node addons for Windows using Visual Studio, it's got detailed instructions and screenshots with full sample code: Writing your first native module for node.js on Windows.

To use this module open cmd.exe and install the module:

npm install windows-eventlog  

Now create a simple script to write some test messages:

var EventLog = require('windows-eventlog').EventLog  
  , logger = new EventLog('dailyjs-logs');

logger.log('Hello from DailyJS');  

This won't run yet, however. Start another cmd.exe, but this time right-click the icon and select "Run as administrator":

Run as administrator

Now the example above should run correctly. Open Event Viewer, then select "Windows Logs", "Application", and look for logs with the source dailyjs-logs (assuming you didn't change it). You should see something like this:

Event Viewer

If portability with existing Unix software is required, then check out José's transport for Winston that uses this module.

Featured

tutorials node windows windows-and-node

Windows and Node: Writing Portable Code

Posted on .

I've been surveying popular Node modules and the nodejs Google Group to find common portability issues people have found when testing modules in Windows.

For the most part, Node code seems very portable -- there are only a few problem areas that seem to crop up frequently. Let's take a look at these problems and the solutions so we can write code that runs everywhere.

Platform-Specific Code

Despite Node code's inherent portability, there are times when platform-specific code is required. This is dealt with in Node's core modules like this:

var isWindows = process.platform === 'win32';

if (isWindows) {  
  // Windows-specific code
}

This example is based on path.js.

For more detailed information on the operating system, the os module can come in handy.

Node's OS module in Windows

File System

Windows can actually accept backslashes or forward slashes as a path separator. This means you don't need to change all of your require calls to use different slashes; most things should just work. There are a few cases where we need to be careful, however, particularly if a path name is absolute or it's going to be displayed somewhere.

One common issue I've found is where the developer has made certain assumptions about the structure of absolute paths. In a commit to Express, Fixed absolute path checking on windows, we can see where the authors have adapted a method called isAbsolute to support Windows:

exports.isAbsolute = function(path){  
  if ('/' == path[0]) return true;
  if (':' == path[1] && '\\' == path[2]) return true;
};

Isaac Schlueter [recommends] [1] using path.resolve to make relative paths absolute in a cross-platform way.

When dealing with fragments of paths, using path.join will automatically insert the correct slash based on platform. For example, the Windows version will insert backslashes:

var joined = paths.join('\\');  

Notice that JavaScript strings require two backslashes because one acts as an escape, so when working with Windows path names don't be surprised if there are lot of double slashes.

Another big source of Windows issues is fs.watch. This module is routinely used by programs that watch for file system changes. Node's documentation makes it clear that the API isn't portable, so the slower but more compatible fs.watchFile can be used instead.

In this patch for the Derby web framework, we can see where the developers opted to branch based on process.platform to use fs.watchFile in Windows, but fs.watch elsewhere.

Text Interfaces

Be aware that not everybody has a super-fancy UTF-8 terminal that supports colours. Certain programs depend on text output, but people may have trouble seeing it correctly if your program relies on symbols their terminal or font doesn't support.

Mocha is a good example of such a program, and in the issue Ability to configure passed/failed checkmarks for the spec reporter, we can see where someone has struggled to read the output with cmd.exe.

Environment

Assuming certain environmental variables will exist (or mean the same thing) on every platform is a good way to create portability headaches.

James Halliday's Browserify had its fair share of Windows issues, which was problematic due to several other popular modules depending on it.

This commit to Browserify demonstrates a fix Christopher Bennage submitted that replaces calls to process.env.HOME with the following:

var home = (process.env.HOME || process.env.USERPROFILE);  

I tried this in Windows 7 and found process.env.HOME wasn't set, but process.env.USERPROFILE worked as expected.

Sockets

Node's TCP sockets are portable, but Unix domain sockets are not. However, Windows has named pipes. The following code is almost exactly the same as the Unix equivalent, it just has a different path to the named pipe:

var net = require('net');

net.createServer(function(socket) {  
  console.log('Connected');
}).listen('\\\\.\\pipe\\named-pipe-test');

Notice the escaped backslashes -- forgetting to insert them here will raise a confusing EACCESS error. In node/test/common.js, there's a branch based on platform to set the name of the pipe so it works in Windows and Unix:

if (process.platform === 'win32') {  
  exports.PIPE = '\\\\.\\pipe\\libuv-test';
} else {
  exports.PIPE = exports.tmpDir + '/test.sock';
}

References

[1]: Best practices for writing cross-platform node applications [2]: Node's documentation [3]: Node's source

Featured

tutorials addons node windows windows-and-node gyp

Windows and Node: Addons

Posted on .

In this article we're going to look at addons. If you're a Node developer working in Windows then this article should give you enough background to at least understand the basic issues surrounding addons, and install them using npm.

Addons are something Unix-based Node developers generally have little trouble with. However, the history of addon support in Windows has been a little bit turbulent. We've seen various solutions come and go -- most notably node-waf and Cygwin -- but the community has now settled on node-gyp by Nathan Rajlich.

Hint: Addons use C or C++ libraries. Node modules may include both addons and JavaScript code.

Isaac Schlueter summarised it in this comment:

Node-waf doesn't work on Windows. We're working on a solution that will make it easier to get a build toolchain in Windows based on node-gyp. Many packages will have to be updated to use this instead, so we're trying to make it as easy a transition as possible.

Installing a Module with Native Code

The fibers module uses node-gyp for building its native components. However, the module's author, Marcel Laverdet, has packaged it in an extremely effective way. Rather than force everybody to build the module, he's included binaries in the npm package. These are not present in the GitHub repository, but are available through npm. This includes both 32 and 64 bit versions.

node-fibers installation in Windows

Therefore, simply running npm install fibers should result in a working module in Windows. The compressed archive on npm actually includes Linux, Mac OS, and Windows binaries, for example: bin/win32-ia32/fibers.node.

Building a Module in Windows

As an exercise, let's build the fibers module. I picked this one because I already know it works -- although there are other modules built with node-gyp, they don't all build correctly in Windows yet.

Building the module requires a few dependencies:

  • A global installation of node-gyp
  • Python 2.7
  • Microsoft Visual Studio ("Express" is free)

Installing node-gyp

The node-gyp module is easy to install, but just make sure it's installed globally so it'll be in your %PATH%:

npm install -g node-gyp  

Installing Python

GYP, or Generate Your Projects, is a build system that uses Python. GypUserDocumentation covers the basics, but from our perspective we just need a working version of Python 2.7.x to use it.

I installed Python 2.7.3 using the MSI installer.

Installing Microsoft Visual Studio

Microsoft provides a free edition of Visual Studio called Visual Studio 2010 Express. I downloaded the ISO and extracted the ISO using 7-Zip. It's 694 MB, so you might want to brew a suitable hot drink while it's downloading.

Installing Visual C++

Fortunately, Microsoft provide this suite of tools and compilers for free with no user registration.

Running Microsoft's IDE

Building the Module

I downloaded the latest zip of node-fibers from GitHub, opened Command Prompt, changed directory to the path of the extracted zip, then ran the following:

set PATH=%PATH%;C:\Python27  
node-gyp configure  
node-gyp build  

Building the fibers module

Once that was done I ran npm test, and the tests all passed. I found it quite satisfying to see Microsoft's compiler actually build something, and although it's not necessary to build the fibers module this way, there are other modules out there that don't include binaries in npm.

Conclusion

Hopefully you now appreciate a little bit about how addons are built in Windows. Although previously the situation was confusing, the community is starting to convert modules to build with node-gyp.

I suspect there will be cases where native code can't be shipped as binaries due to licensing constraints, but it would be encouraging to see more addons include binaries for Windows.

Featured

tutorials node windows windows-and-node

Windows and Node: Windows Performance Monitor

Posted on .

It's time to take a look at a Windows-oriented Node module to see how it works. Before getting messy with C, C++, and all that native module stuff, let's keep it simple by looking at something that communicates with Windows programs using Node's streams.

Windows Performance Monitor

Windows Performance Monitor provides extremely detailed logging, featuring a wide array of counters, event trace data, and configuration information. The command-line tool, typeperf.exe can write some of this data to a command window.

For example, typeperf "\Memory\Available bytes" "\processor(_total)\% processor time" will display processor and memory counters. The output looks like this on my computer:

typeperf

Why do I mention this? Well, the Node perfmon module is a wrapper around typeperf that provides a ReadableStream-based API. This is an idiomatic module that demonstrates one way of working with an existing program that comes bundled with Windows.

The perfmon Module

To try it out, open a command window and make a directory:

cd Documents\Code\  
mkdir perf-example  
cd perf-example  

Then install perfmon:

npm install perfmon  

Once that's done, create a JavaScript file that uses the perfmon module to gather some data:

var perfmon = require('perfmon');

perfmon('\\processor(_total)\\% processor time', function(err, data) {  
  console.log(data);
});

Running it should display some logging. Press ctrl-c to stop it.

Child Processes

The author has written this by using spawn from the child_process module. In fact, we can execute any executable using this module. Try the following script:

var exec = require('child_process').exec;

exec('echo %PATH%', function(err, stdout, stderr) {  
  console.log('PATH:', stdout);
});

The output should look similar to the following screenshot, but it may vary depending on what you've got installed:

PATH

The child_process API is exactly the same in Unix, as we saw in the Unix and Node posts.

Portability

Does this mean Node programs are generally portable between Unix and Windows? Well, as you can see in this example, Node's standard libraries look the same. It's just the part that touches the operating system that may look different. In this example, the part that reads echo %PATH% would be different in Unix.

We'll look at other portability issues as this series progresses. For now, your homework is to find more Windows-oriented Node modules and see if you can understand the basic principles at work. The Node documentation will be indispensable for this!