JeringTech / Javascript.NodeJS

Invoke Javascript in NodeJS, from C#
Other
463 stars 43 forks source link

Can I use chrome-remote-interface with Jering.Javascript.NodeJS? #103

Closed zydjohnHotmail closed 3 years ago

zydjohnHotmail commented 3 years ago

Hello: I happen to find this great repo., and I want to know if I can use it to run some Node.js script, in which npm package ‘chrome-remote-interface’ is used. The following is my situation: My OS: Windows 10 (latest version) Node.js: version 15.9.0 (rather new version, even the current version is: 15.10.0) I installed Google Chrome in my Windows PC (Version 88.0.4324.190) I run chrome with this command: chrome --remote-debugging-port=9222 I have installed the following npm packages: C:\Temp>type package.json { "name": "Test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "chrome-remote-interface": "^0.29.0", "express": "^4.17.1", "node-fetch": "^2.6.1", } }

The following is the content for index.js: C:\Temp>type index.js const CDP = require('chrome-remote-interface');

CDP(async(client) => { const {Network, Page, Runtime} = client; try { await Network.enable(); await Page.enable(); await Network.setCacheDisabled({cacheDisabled: true}); await Page.navigate({url: 'https://www.google.com/'}); await Page.loadEventFired(); const result = await Runtime.evaluate({ expression: 'document.documentElement.outerHTML' }); const html = result.result.value; console.log(html); } catch (err) { console.error(err); } finally { client.close(); } }).on('error', (err) => { console.error(err); });

I can run my Node.js script (index.js) without any issue: C:\Temp> node index.js

My question is: how I can do the same with Jering.Javascript.NodeJS? I have downloaded the repo in zip format, and unzip it and tried to understand it. I am using Visual Studio 2019 (Version 16.8.6), when I tried to rebuild the repo., I got 8 errors: Error NU1403 Package content hash validation failed for Microsoft.DotNet.PlatformAbstractions.2.1.0. The package is different than the last restore. Package content hash validation failed for Microsoft.NETCore.Platforms.2.0.0. The package is different than the last restore. Package content hash validation failed for Microsoft.NETCore.Targets.1.1.0. The package is different than the last restore. Package content hash validation failed for runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl.4.3.0. The package is different than the last restore. Package content hash validation failed for runtime.native.System.4.3.0. The package is different than the last restore. ….. I wish I can port this repo to target .Net 5.0, which will be the future for all .Net platform. But I don’t know how to fix those above errors first. Besides, I looked at the repo., I have no idea how I can set up one small test case, so I can test my Node.js script: index.js Please advise!

JeremyTCD commented 3 years ago

My question is: how I can do the same with Jering.Javascript.NodeJS?

Hey! This is how you'd use a library (I'm not familiar with chrome-remote-interface so I made some assumptions, notes in comments):

  1. Create interop.js:

    const CDP = require('chrome-remote-interface');
    
    module.exports = (callback, pageUrl) => {
        CDP(async (client) => {
            const { Network, Page, Runtime } = client;
            try {
                await Network.enable();
                await Page.enable();
                await Network.setCacheDisabled({ cacheDisabled: true });
                await Page.navigate({ url: pageUrl}); // Assuming you want to specify different urls
                await Page.loadEventFired();
                const result = await Runtime.evaluate({
                    expression: 'document.documentElement.outerHTML'
                });
                const html = result.result.value;
                console.log(html);
    
                // Assuming html is a string and you want to return it
                callback(null, html);
            } catch (err) {
                console.error(err);
    
                // Exception will be thrown in .Net process
                callback(err);
            } finally {
                client.close();
            }
        }).on('error', (err) => {
            console.error(err);
    
            // Assuming you want execution to stop when the error event fires
            // Exception will be thrown in .Net process
            callback(err);
        });
    }
  2. In C#:

    string html = await StaticNodeJSService.InvokeFromFileAsync<string>(pathToInteropFile, args: new[] { "https://www.google.com/"}).ConfigureAwait(false);

If you want to specify a relative pathToInteropFile, see Configuring INodeJSService and NodeJSProcessOptions.

Let me know if you need more help.

I wish I can port this repo to target .Net 5.0, which will be the future for all .Net platform.

The latest commits target .Net 5.0. Latest published package, 6.0.0-beta.2 targets .Net 5.0. If you're open to contributing in other ways, help with this list of thing to do would be much appreciated.

As for build errors, this project uses the RestorePackagesWithLockFile flag to lock dependencies. Looks like that's what you're having trouble with.

For what it's worth, every merge into master is built and tested in clean Windows, MacOS and Linux VMs. Haven't had issues restoring dependencies there. The VMs are using .Net SDK version 5.0.103 (same as my local machine).

Googling surfaced this issue on lock files, might be helpful. I think people there can provide better assistance with build issues!

zydjohnHotmail commented 3 years ago

Hello: Thank you very much for your help. I tried to use nuget package with 6.0.0-beta.2, and follow your instructions, and it works.
But I have some minor question: If I install npm chrome-remote-interface using global option, but it seems not working. So I have to install it inside the folder of the C# project root folder. I will do more testing, and I will ask more questions if any. Thanks!

JeremyTCD commented 3 years ago

If I install npm chrome-remote-interface using global option, but it seems not working. So I have to install it inside the folder of the C# project root folder.

Hey yeah this has to do with how Node.js resolves modules - loading from node_modules folders. Basically Node.js looks in node_modules in the project directory, if it can't find the module it looks in node_modules in the project directory's parent and so on. When you use this library the project directory is set using NodeJSProcessOptions.ProjectPath.

Feel free to open another issue if you have more questions!