DEV Community

Masui Masanori
Masui Masanori

Posted on

[Windows][Node.js][TypeScript] Get installed printer driver names

Intro

I wanted to print PDF files.
Before printing, I wanted to search installed printer driver names and choose one to use.
But because I got some problems when I tried getting printer names, I will note how to avoid them.

Environments

  • Windows 10 ver.20H2
  • Node.js ver.16.2.0
  • TypeScript ver.4.2.4
  • pdf-to-printer ver.2.0.4
  • iconv-lite ver.0.4.24

Getting printer driver names

I can get installed printer driver names by "pdf-to-printer".

import ptp from "pdf-to-printer";
async function print()
{
    const printerName = 'Microsoft Print to PDF';
    const printers = await ptp.getPrinters();
    for(const p of printers)
    {
        console.log(`PRINTER Name: ${p.name} compare: ${p.name === printerName}`);
    }
}
print();
Enter fullscreen mode Exit fullscreen mode

Result

PRINTER Name: OneNote for Windows 10 compare: false
PRINTER Name: OneNote (??????) compare: false
PRINTER Name: OneNote (Desktop) compare: false
PRINTER Name: Microsoft XPS Document Writer compare: false
PRINTER Name: Microsoft Print to PDF compare: true
PRINTER Name: Fax compare: false
Enter fullscreen mode Exit fullscreen mode

Problem

Actualy, the second printer driver name was "OneNote (デスクトップ)".

Because the name was garbled, all of the comparing will be failed.
And I will get an error if I do like below.

...
    const printers = await ptp.getPrinters();
    for(const p of printers)
    {
        if(p.name.startsWith('OneNote ('))
        {
            console.log(p.name);        
            ptp.print('C:/Users/example/OneDrive/Documents/workspace/print-pdf-sample/sample.pdf',
            {
                printer: p.name,
            })
            .then(_ => console.log('OK'))
            .catch(error => console.error(error));
            break;
        }
    }
...
Enter fullscreen mode Exit fullscreen mode

Result

OneNote (??????)
Error: Command failed: C:\Users\example\OneDrive\Documents\workspace\print-pdf-sample\node_modules\pdf-to-printer\dist\SumatraPDF.exe -print-to OneNote (??????) -silent C:/Users/example/OneDrive/Documents/workspace/print-pdf-sample/sample.pdf

    at ChildProcess.exithandler (node:child_process:326:12)
    at ChildProcess.emit (node:events:365:28)
    at maybeClose (node:internal/child_process:1067:16)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:301:5) {
  killed: false,
  code: 1,
  signal: null,
  cmd: 'C:\\Users\\example\\OneDrive\\Documents\\workspace\\print-pdf-sample\\node_modules\\pdf-to-printer\\dist\\SumatraPDF.exe -print-to OneNote (??????) -silent C:/Users/example/OneDrive/Documents/workspace/print-pdf-sample/sample.pdf'
}
Enter fullscreen mode Exit fullscreen mode

How to get the printer driver names?

According to the source code, "pdf-to-printer" uses "wmic printer get deviceid,name".

Even if I execute the command directly in PowerShell, the name is also garbled.

Change the text encodings (failed)

I can run commands by "exec", "execFile" of "child_process".

async function print()
{
    execFile ("powershell", [`Get-Printer`], { encoding: 'utf8'}, (error, stdout) =>{
        console.log("execFile");
        console.log(stdout);
        console.log(error);
    });
    exec('powershell Get-Printer', (error: any, stdout: any, strerr: any) => {
        console.log("exec");
        console.log(stdout);
        console.log(error);
    });
...
}
Enter fullscreen mode Exit fullscreen mode

I also try changing text encodings by "iconv-lite" or some other way.

async function print()
{
    execFile ("powershell", [`Get-Printer`], { encoding: 'utf8'}, (error, stdout) =>{
        console.log("execFile");
        const buf = Buffer.from(stdout, 'binary');
        const dec = iconv.decode(buf, 'UTF-8');
        console.log(dec);
        console.log(error);
    });
    exec('powershell $OutputEncoding = [Text.UTF8Encoding]::UTF8;Get-Printer', (error: any, stdout: any, strerr: any) => {
        console.log("Exec");
        console.log(stdout);
        console.log(error);
    });
...
}
Enter fullscreen mode Exit fullscreen mode

But the results aren't changed anything.
I think it's because the texts has been garbled before I get them.

Change OS encodings

This problem comes from the terminals text encodings aren't "UTF-8".
So I change them from the settings.

Steps

  1. Open Settings > Time & Language > Region > Additional date, time & regional settings > Region.
  2. Click "Change system locale..." in "Administrative" tab.
  3. Check "Beta: Use Unicode UTF-8 for worldwide language support"
  4. Restart the computer

Alt Text

After that, I can get Japanese printer driver names.

async function print()
{
    execFile ("powershell", [`Get-Printer`], { encoding: 'utf8'}, (error, stdout) =>{
        console.log("execFile");
        console.log(stdout);
        console.log(error);
    });
    const printers = await ptp.getPrinters();
    for(const p of printers)
    {
        console.log(`PRINTER Name: ${p.name}`);
    }
...
}
Enter fullscreen mode Exit fullscreen mode

Results

PRINTER Name: OneNote (Desktop)
PRINTER Name: OneNote for Windows 10
PRINTER Name: OneNote (デスクトップ)
PRINTER Name: Microsoft XPS Document Writer
PRINTER Name: Microsoft Print to PDF
PRINTER Name: Fax
execFile

Name                           ComputerName    Type         DriverName                PortName        Shared   Publishe
                                                                                                               d
----                           ------------    ----         ----------                --------        ------   --------
OneNote (Desktop)                              Local        Send to Microsoft OneN... nul:            False    False
OneNote for Windows 10                         Local        Microsoft Software Pri... Microsoft.Of... False    False
OneNote (デスクトップ)                               Local        Send to Microsoft OneN... nul:            False    False
Microsoft XPS Document Writer                  Local        Microsoft XPS Document... PORTPROMPT:     False    False
Microsoft Print to PDF                         Local        Microsoft Print To PDF    PORTPROMPT:     False    False
Fax                                            Local        Microsoft Shared Fax D... SHRFAX:         False    False
Enter fullscreen mode Exit fullscreen mode

Top comments (0)