Determine if software is installed and what version on Mac in Node.js JavaScript

≯℡__Kan透↙ 提交于 2020-01-15 10:14:07

问题


I am in a node environment on Mac within a Electron application and I am needing to:

  1. test if Photoshop is installed
  2. get version of installed Photoshop
  3. launch Photoshop

This was all extremely easy to do in windows. I branch on nodejs os modules platform method so if 'Darwin' I need to do the above things.

I am not a Mac user so I do not know much about the processes on Mac.

I can parse .plist files if need be but poking around users lib preference folder hasn't showed up much. There are Photoshop specific .psp preference files but I have no way to see whats inside them and merely checking to see if there is a Photoshop file located in folder seems way to sloppy to me plus I need to get the version.

Solution

After some research I came across the mac system profiler utility which seems to exist on all mac operating systems.

using node's exec module I get all installed applications and some details about each that look like

TextEdit:

 Version: 1.13
 Obtained from: Apple
 Last Modified: 6/29/18, 11:19 AM
 Kind: Intel
 64-Bit (Intel): Yes
 Signed by: Software Signing, Apple Code Signing Certification Authority, Apple Root CA
 Location: /Applications/TextEdit.app

now I just needed to write a simple parser to parse the results which were large with over 335 applications into json for easy querying.

import { exec } from 'child_process';

let proc = exec( 'system_profiler SPApplicationsDataType -detailLevel mini' );
let results = '';
proc.stdout.on( 'data', ( data ) => { results += `${ data }`; } );
proc.on( 'close', async ( code ) =>
{
    let parsed = await this.sysProfileTxtToJson( results );
} );

the sysProfileTxtToJson is my little parsing method

now parsed is a json object that I query to determine if photoshop is installed and if multiple version which is the latest version.

here is the parsing method of which needs improved

sysProfileTxtToJson ( data: string )
{
    return new Promise<any>( ( res ) =>
    {
        let stream = new Readable();
        stream.push( data );
        stream.push( null );

        let lineReader = createInterface( stream );
        let apps = { Applications: [] };
        let lastEntry = '';
        let appPrefix = '    ';
        let appPropertyPrefix = '      ';
        let lastToggle, props = false;
        lineReader.on( 'line', ( line: string ) =>
        {
            if ( line == '' && !lastToggle )
            {
                props = false;
                return;
            }

            if ( line.startsWith( appPrefix ) && !props )
            {
                lastEntry = line.trim().replace( ':', '' );
                lastToggle = true;
                let current = {};
                current[ "ApplicationName" ] = lastEntry
                apps.Applications.push( current );
                props = true;
                return;
            }

            if ( line.startsWith( appPropertyPrefix ) && props )
            {
                lastToggle = false;
                let tokens = line.trim().split( ':' );
                let last = apps.Applications[ apps.Applications.length - 1 ];
                last[ tokens[ 0 ] ] = tokens[ 1 ].trim();
            }
        } );

        lineReader.on( 'close', () =>
        {
            res( apps );
        } );
    } );
}

回答1:


There are several features in AppleScript which can be utilized to achieve your requirement. Consider shelling out the necessary AppleScript/osascript commands via nodejs.


Let's firstly take a look at the pertinent AppleScript commands...

AppleScript snippets:

  1. The following AppleScript snippet returns the name of whichever version of Photoshop is installed (E.g. Photoshop CS5, Photoshop CS6, Photoshop CC, etc ...). We'll need the name to be able to successfully launch the application.

    tell application "Finder" to get displayed name of application file id "com.adobe.Photoshop"
    

    Note: The snippet above errors if Photoshop is not installed, so we can also utilize this to determine if the application is installed or not.

  2. The following snippet obtains whichever version of Photoshop is installed:

    tell application "Finder" to get version of application file id "com.adobe.Photoshop"
    

    This returns a long String indicating the version. It will be something like this fictitious example:

    19.0.1 (19.0.1x20180407 [20180407.r.1265 2018/04/12:00:00:00) © 1990-2018 Adobe Systems Incorporated


Launching Photoshop:

After it has been inferred that PhotoShop is installed consider utilizing Bash's open command to launch the application. For instance:

open -a "Adobe Photoshop CC"

Example node application:

The following gist demonstrates how the aforementioned commands can be utilized in node.

Note: The gist below is utilizing shelljs's exec command to execute the AppleScript/osascript commands. However you could utilize nodes builtin child_process.execSync() or child_process.exec() instead.

const os = require('os');
const { exec } = require('shelljs');

const APP_REF = 'com.adobe.Photoshop';
const isMacOs = os.platform() === 'darwin';

/**
 * Helper function to shell out various commands.
 * @returns {String} The result of the cmd minus the newline character.
 */
function shellOut(cmd) {
  return exec(cmd, { silent: true }).stdout.replace(/\n$/, '');
}


if (isMacOs) {

  const appName = shellOut(`osascript -e 'tell application "Finder" \
      to get displayed name of application file id "${APP_REF}"'`);

  if (appName) {
    const version = shellOut(`osascript -e 'tell application "Finder" \
        to get version of application file id "${APP_REF}"'`).split(' ')[0];

    console.log(version); // Log the version to console.

    shellOut(`open -a "${appName}"`); // Launch the application.
  } else {
    console.log('Photoshop is not installed');
  }
}


来源:https://stackoverflow.com/questions/52978279/determine-if-software-is-installed-and-what-version-on-mac-in-node-js-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!