Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getting powershell output back into javascript #147

Open
Thraxll opened this issue Mar 7, 2022 · 5 comments
Open

getting powershell output back into javascript #147

Thraxll opened this issue Mar 7, 2022 · 5 comments

Comments

@Thraxll
Copy link

Thraxll commented Mar 7, 2022

How can I get Powershell's output back into javascript as a object or array? My code is below. I'd like to be able to display the output of the command via html page.


const { PowerShell } = require('node-powershell');

const poshInstance = async () =>  {
  const ps = new PowerShell({
    executionPolicy: 'Bypass',
    noProfile: true
  });

  const getLG = PowerShell.command`Get-LocalGroup`
  const output = await ps.invoke(getLG)
  await ps.dispose()
  console.log(output)
}

poshInstance()

@Danielv123
Copy link

Hi, I have been doing this for an automation project

let output = await shell.invoke(`Get-VM -Server ${server.ip} | Select-Object -Property Name,Uid,PowerState | ConvertTo-Json -Compress -Depth 99`);

The output includes some whitespace and stuff, so I remove that

console.log(JSON.parse(output.raw.replace("\u001b[?1h\u001b[?1l", "").replace("�[?1h�[?1l�[?1h�[?1l", "")));

And thats it. Seems a bit fragile though, but I run everything in a docker container so hopefully won't have to worry.

@Danielv123
Copy link

Danielv123 commented May 8, 2022

New update on this. It seems that different commands produce different junk around the command. It seems deterministic, but very annoying. I do not get those warnings when running the same command in my normal powershell window, so not sure where they come from.

Command: Get-Datastore -Server ${server.ip} | Select-Object -Property FileSystemVersion, DatacenterId, ParentFolderId, DatastoreBrowserPath, FreeSpaceMB, CapacityMB, Accessible, Type, StorageIOControlEnabled, CongestionThresholdMillisecond, State, CapacityGB, FreeSpaceGB, Name, Id, Uid | ConvertTo-Json -Compress -Depth 99

image

Output when running through child-shell:

�[33;1mWARNING: The 'Accessible' property of Datastore type is deprecated. Use the 'State' property instead.�[0m
[{"FileSystemVersion":"6.82","DatacenterId":"Datacenter-ha-datacenter","ParentFolderId":"Folder-ha-folder-datastore","DatastoreBrowserPath":"vmstores:/192.168.10.52@443/ha-datacenter/ssd1","FreeSpaceMB":603047.0,"CapacityMB":953600.0,"Accessible":true,"Type":"VMFS","StorageIOControlEnabled":true,"CongestionThresholdMillisecond":30,"State":0,"CapacityGB":931.25,"FreeSpaceGB":588.9130859375,"Name":"ssd1","Id":"Datastore-61e490a4-59f7bc8a-f1d8-90b11c5a54ae","Uid":"/[email protected]:443/Datastore=Datastore-61e490a4-59f7bc8a-f1d8-90b11c5a54ae/"},{"FileSystemVersion":"6.82","DatacenterId":"Datacenter-ha-datacenter","ParentFolderId":"Folder-ha-folder-datastore","DatastoreBrowserPath":"vmstores:/192.168.10.52@443/ha-datacenter/ssd2","FreeSpaceMB":245392.0,"CapacityMB":953600.0,"Accessible":true,"Type":"VMFS","StorageIOControlEnabled":true,"CongestionThresholdMillisecond":30,"State":0,"CapacityGB":931.25,"FreeSpaceGB":239.640625,"Name":"ssd2","Id":"Datastore-61e490ad-d1082309-7bc2-90b11c5a54ae","Uid":"/[email protected]:443/Datastore=Datastore-61e490ad-d1082309-7bc2-90b11c5a54ae/"},{"FileSystemVersion":"6.82","DatacenterId":"Datacenter-ha-datacenter","ParentFolderId":"Folder-ha-folder-datastore","DatastoreBrowserPath":"vmstores:/192.168.10.52@443/ha-datacenter/ssd3","FreeSpaceMB":569929.0,"CapacityMB":953600.0,"Accessible":true,"Type":"VMFS","StorageIOControlEnabled":true,"CongestionThresholdMillisecond":30,"State":0,"CapacityGB":931.25,"FreeSpaceGB":556.5712890625,"Name":"ssd3","Id":"Datastore-61e490b8-58dac0d8-f426-90b11c5a54ae","Uid":"/[email protected]:443/Datastore=Datastore-61e490b8-58dac0d8-f426-90b11c5a54ae/"},{"FileSystemVersion":"3.0","DatacenterId":"Datacenter-ha-datacenter","ParentFolderId":"Folder-ha-folder-datastore","DatastoreBrowserPath":"vmstores:/192.168.10.52@443/ha-datacenter/TRUENAS","FreeSpaceMB":20457549.0,"CapacityMB":20582128.0,"Accessible":true,"Type":"NFS","StorageIOControlEnabled":false,"CongestionThresholdMillisecond":30,"State":0,"CapacityGB":20099.734375,"FreeSpaceGB":19978.0751953125,"Name":"TRUENAS","Id":"Datastore-192.168.10.160:/mnt/hddpool/vmware","Uid":"/[email protected]:443/Datastore=Datastore-192.168.10.160:&slash;mnt&slash;hddpool&slash;vmware/"}]

I solved it by adding $WarningPreference = 'SilentlyContinue'; before calling my command.

@mayerlench
Copy link

Hi, I have been doing this for an automation project

let output = await shell.invoke(`Get-VM -Server ${server.ip} | Select-Object -Property Name,Uid,PowerState | ConvertTo-Json -Compress -Depth 99`);

The output includes some whitespace and stuff, so I remove that

console.log(JSON.parse(output.raw.replace("\u001b[?1h\u001b[?1l", "").replace("�[?1h�[?1l�[?1h�[?1l", "")));

And thats it. Seems a bit fragile though, but I run everything in a docker container so hopefully won't have to worry.

You are seeing that "junk" output because all your PS logs are getting clumped into one output.

Do something like this and you will get a clean JSON output
Using the stream from the instance of node-powershell you can log each time data is output
You will see that you have multiple outputs
ps.streams.stdout.on('data', function (data) { console.log(data) })

@stuieordie
Copy link

stuieordie commented May 12, 2022

Here's an example I'm using with node-powershell version 5.0.1
Things to note:

  • inside the back-ticks after Shell.Powershell, you can basically write a power shell script (you need to escape pipes) but you can use variables, multiples lines etc
  • If the code executes successfully, a response object is returned with the field 'raw' which contains the output. You can turn this field back into a Node JSON object to do further processing with the JSON.parse() method as long as you convert the powershell to JSON first
  • If PowerShell returns an error, it gets caught in the catch block where you can print the errors or whatever you like with it
const Shell = require('node-powershell');

  let psOut = await Shell.PowerShell.$`
    $myuser = "stuieordie"
    Get-ADUser $myuser \| ConvertTo-Json
  `
  .then(response => {
    // return the entire response object
    // return response
    // Or parse the raw field and return a JSON object of the command output
    return JSON.parse(response.raw)
  })
  .catch(err => {
    console.log(err)
  });
console.log(psOut.SamAccountName)
'stuieordie'

Alternatively if you want to use async/await this is another example

async function getADUser(username) {
    try {
        let getUserObj = await Shell.PowerShell.$`
    	    $strDC = Get-ADDomainController -Discover -DomainName example.com \| Select-Object -ExpandProperty HostName
    	    Get-ADUser -Server $strDC -Identity ${getObj.value} \| ConvertTo-Json
  	`
        let userObj = {
            "userName": JSON.parse(getUserObj.raw).SamAccountName,
            "active": JSON.parse(getUserObj.raw).Enabled.toString().toLowerCase(),
            "id": JSON.parse(getUserObj.raw).SamAccountName
        }
      return userObj
        } catch (error) {
            let userObj = []
            return userObj
	  }
  }
getADUser("stuieordie")

@msdiniz
Copy link

msdiniz commented Jan 3, 2023

Here's an example I'm using with node-powershell version 5.0.1 Things to note:

  • inside the back-ticks after Shell.Powershell, you can basically write a power shell script (you need to escape pipes) but you can use variables, multiples lines etc
  • If the code executes successfully, a response object is returned with the field 'raw' which contains the output. You can turn this field back into a Node JSON object to do further processing with the JSON.parse() method as long as you convert the powershell to JSON first
  • If PowerShell returns an error, it gets caught in the catch block where you can print the errors or whatever you like with it
const Shell = require('node-powershell');

  let psOut = await Shell.PowerShell.$`
    $myuser = "stuieordie"
    Get-ADUser $myuser \| ConvertTo-Json
  `
  .then(response => {
    // return the entire response object
    // return response
    // Or parse the raw field and return a JSON object of the command output
    return JSON.parse(response.raw)
  })
  .catch(err => {
    console.log(err)
  });
console.log(psOut.SamAccountName)
'stuieordie'

Alternatively if you want to use async/await this is another example

async function getADUser(username) {
    try {
        let getUserObj = await Shell.PowerShell.$`
    	    $strDC = Get-ADDomainController -Discover -DomainName example.com \| Select-Object -ExpandProperty HostName
    	    Get-ADUser -Server $strDC -Identity ${getObj.value} \| ConvertTo-Json
  	`
        let userObj = {
            "userName": JSON.parse(getUserObj.raw).SamAccountName,
            "active": JSON.parse(getUserObj.raw).Enabled.toString().toLowerCase(),
            "id": JSON.parse(getUserObj.raw).SamAccountName
        }
      return userObj
        } catch (error) {
            let userObj = []
            return userObj
	  }
  }
getADUser("stuieordie")

Thanks for the neat code.
Any suggestions how to pass { executionPolicy: 'Bypass', noProfile: true } to Shell.PowerShell?
I tried but it did not work, saying that only newing it we can provide parameters.

let psOut = await Shell.PowerShell({
         executionPolicy: 'Bypass', 
         noProfile: true
     }).$`
     $myuser = "stuieordie"
     Get-ADUser $myuser \| ConvertTo-Json

If no other way, I think that I'll need to new it and psOut.invoke(somecmd)...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants