Running Puppeteer on WSL2 controlling the Chrome on Windows
Asked Answered
U

2

9

I'm trying to get to run puppeteer on WSL2. I've tried using a remote display via VcXsvr but my firewall settings and host have custom changes and I've frankly given up seeing that https://learn.microsoft.com/en-us/windows/wsl/tutorials/gui-apps is in the works.

So in the meantime I'm trying to connect to the Windows Chrome install directly using the following test code:

const puppeteer = require('puppeteer');

const EXECUTABLE_PATH = '/mnt/c/Users/[username]/AppData/Local/Google/Chrome/Application/chrome.exe';
const USER_DATA_DIR = 'C:\\Users\\[username]\\AppData\\Local\\Google\\Chrome\\User Data';


const url = process.argv[2];
console.log(url);
if (!url) {
    throw "Please provide URL as a first argument";
}
async function run () {
    try {
        const browser = await puppeteer.launch({
            executablePath: EXECUTABLE_PATH,
            userDataDir: USER_DATA_DIR,  
            headless: false,
            ignoreDefaultArgs: ['--disable-extensions'],

        });
        const page = await browser.newPage();
        await page.goto(url);
        await page.screenshot({path: 'screenshot.png'});
        browser.close();
    } catch(err){
        console.log(err)
    }
}
run();

I'm seeing chrome open but then showing the following error:

Error: Failed to launch the browser process!
[4348:24368:0526/115831.752:ERROR:cache_util_win.cc(20)] Unable to move the cache: Access is denied. (0x5)
[4348:24368:0526/115831.753:ERROR:cache_util.cc(144)] Unable to move cache folder C:\Users\[username]\AppData\Local\Google\Chrome\User Data\ShaderCache\GPUCache to C:\Users\[username]\AppData\Local\Google\
Chrome\User Data\ShaderCache\old_GPUCache_001
[4348:24368:0526/115831.753:ERROR:disk_cache.cc(184)] Unable to create cache
[4348:24368:0526/115831.753:ERROR:shader_disk_cache.cc(606)] Shader Cache Creation failed: -2


TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md

    at onClose (~/development/my-puppeteer-app/node_modules/puppeteer/lib/launcher/BrowserRunner.js:189:20)
    at Interface.helper_1.helper.addEventListener (~/development/my-puppeteer-app/node_modules/puppeteer/lib/launcher/BrowserRunner.js:179:65)
    at Interface.emit (events.js:203:15)
    at Interface.close (readline.js:397:8)
    at Socket.onend (readline.js:173:10)
    at Socket.emit (events.js:203:15)
    at endReadableNT (_stream_readable.js:1145:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)

I cannot figure out how to fix this from the provided troubleshooting link and cannot find any other sources where this is shown. Any suggestions would be welcome.

Unbeaten answered 26/5, 2021 at 11:2 Comment(6)
Did you try specifying data dir value : USER_DATA_DIR the same format as EXECUTABLE_PATH starting with /mnt/c/...Heartwood
I tried that but my understanding is that this is being used by Chrome thus under windows. If I change this I get a chrome dialog popping open saying that Chrome cannot write to it's data directory. The actual chrome window never opens.Unbeaten
You may also try to specify a directory other than Chrome's actual data directory.Heartwood
That actually resolved that issue. I've got another one but will update this post once I'm certain it's not related. Thanks.Unbeaten
@Unbeaten any luck? I've got Chrome opening, but Puppeteer complains "connect ECONNREFUSED 127.0.0.1:54619".Capparidaceous
@MonkeyBoson I gave up. Shortly after this post Microsoft released the Windows 11 Preview on insider. This natively supports Linux graphics on WSL and I ended up just using that instead, so my paths are now 'native to linux'.Unbeaten
M
1

There is yet another way that may be more appropiate for the developing environment used. Instead of installing a whole X11 server on wsl2 , you can just run an instance of chrome in debugging mode in Windows and connect puppeteer to it via the WSL Network Interface.

I describe below the steps:

  • Install chromium/chrome on Windows choco install chromium
  • In puppeteer use puppeteer-core instead npm i puppeteer-core

For each session then do:

  • (In Windows) Open chromium in debugging mode
Start-Process -FilePath "C:\Program Files\Chromium\Application\chrome.exe" -ArgumentList "--remote-debugging-port=21222"
  • (In Windows) Open the ports on the Windows Firewall
> Advanced firewall Settings > Add new rule
            > Allow in > "allow-in-21222-chrome-debug"
            > Allow out > "allow-out-21222-chrome-debug"
  • (In Windows) Check for your Windows side WSL Ip address
ipconfig /all
# In my case is 172.19.192.1
  • (In Windows) Execute the port forwarding command in an elevated command prompt
netsh interface portproxy add v4tov4 listenport=21222 listenaddress=172.19.192.1 connectport=21222 connectaddress=127.0.0.1
  • (In Linux) Modify slightly your puppeteer script (initiate it this way)
const puppeteer = require('puppeteer-core');

async function main () {

    const browserURL = 'http://172.19.192.1:21222';
    const browser = await puppeteer.connect({browserURL});

}

Now you can run the node command from WSL2 , and it will work nicely.

Moralist answered 13/5 at 16:12 Comment(1)
How can I create this firewall rule in Windows Defender Firewall?Circumstantial
B
0

Here is my solution with a different path:

Please note the path I use for Chrome executable as I think that is the OP's issue

const puppeteer = require('puppeteer-core');
const { exec } = require('child_process');
const chromeExecutable =      
'/mnt/c/Program Files/Google/Chrome/Application/chrome.exe';

    
    // Node.js Puppeteer - launch devtools locally
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    const openDevtools = async (page, client) => {
      // get current frameId
      const frameId = page.mainFrame()._id;
      // get URL for devtools from scraping browser
      const { url: inspectUrl } = await client.send('Page.inspect', {
        frameId,
        executablePath: chromeExecutable,
      });
      // open devtools URL in local chrome
      exec(`"${chromeExecutable}" "${inspectUrl}"`, (error) => {
        if (error) throw new Error('Unable to open devtools: ' + error);
      });
      // wait for devtools ui to load
      await delay(5000);
    };

    // Create a new page in the browser
    const page = await browser.newPage();

    // Create a new CDPSession in the browser
    const client = await page.target().createCDPSession();
    await openDevtools(page, client);

I didn't post all the code because it would have been unnecessary, but this is my solution to the problem of getting dev tools open.

Bernstein answered 6/1 at 18:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.