Сheck if the plugin exists for the user

I’m making a UXP plugin for Photoshop

My plugin runs other plugins installed on the user.

How can I check if a given plugin exists for a user?

It depends on what type of plugin you check.
If you need to check installed UXP plugins on Photoshop, you could get list of UXP plugins through pluginManager.

//manifest.json
"requiredPermissions": {
        "webview": {
          "allow": "yes",
          "domains": ["https://somewhere.com"]
        },
        "localFileSystem": "request",
        "clipboard": "readAndWrite",
        "allowCodeGenerationFromStrings": true,
        "ipc": {
         // you must turn this flag on
          "enablePluginCommunication": true
        }
    },
//JavaScript
const { entrypoints, pluginManager} = require("uxp");

/*
 listing plugins installed on Photoshop.
 Set<PluginObject>
*/
console.log(pluginManager.plugins);

I remind you not to forget set the “enablePluginCommunicatio” flag on manifest.

https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Modules/uxp/Plugin%20Manager/Plugin/

the plugin that I’m trying to call is not a UXP plugin and it’s not mine, that is, it’s not part of my plugin or its separate tab

The user downloads it separately on our website and installs it independently

Now the check for availability is done like this:
I’m trying to launch this plugin through BatchPlay, and then I look in the history of Photoshop, if it is there, it means it was called and the plugin exists, if it is not in the history, then it was not called and the user does not have the plugin

But this system is too unstable and I would like to do some kind of direct verification of its presence

There are ideas to look at the files in the folder where it should be, but so far I’m getting an error saying that the fs module was not found when I try to execute const fs = require('fs')

Asking for Photoshop system information is an expensive call but all the plugins are listed there. Here is a script I use to make sure all the SDK plugins are installed. This is ExtendScript, you will need to convert to UXP.

// Version: 2019.4.16

main();

function main() {

LogMessage( "Starting test: FindPluginInSystemInfo:" );

var fileLog = new File( "~/Desktop/FindPluginInSystemInfo.log" );
fileLog.open( "w" );
var errors = 0;
var sysInfo = app.systemInformation;
var failStart = sysInfo.search( "Plug-ins that failed to load:" );
if ( failStart == -1 ) {
    errors++;
    fileLog.writeln( "No failed to load found" );
}
var failEnd = sysInfo.search( "Extensions:");
if ( failEnd == -1 ) {
    errors++;
    fileLog.writeln( "No flash found" );
}
if ( failEnd < failStart ) {
    errors++;
    fileLog.writeln( "failEnd < failStart" );
}
   
// TODO double check the statistics version, "Generic Plug-in" and 3dsimulator 
// one plug-in could have more than one entry, statistics and SelectoramaShape
// some plug-ins don't show up, see above TODO to confirm
var pluginList = [ 
 "AutomationFilter",     "ColorMunger",         "Dissolve",    "Getter", 
 "GradientImport",       "Hidden",              "History",     "LayerFormat", 
 "Listener",             "Measurement Sample",  "NearestBase", "Outbound", 
 "Poor Man's Type Tool", "Propetizer",          "Selectorama", "Shape", 
 "SimpleFormat",         "Entropy",             "Kurtosis",    "Maximum",
 "Mean",                 "Median",              "Minimum",     "Range", 
 "Skewness",             "Standard Deviation",  "Summation",   "Variance", 
 "TextAuto",             "TextFormat" ];
                   
if ( $.os.search(/windows/i) != -1 )
	pluginList.push( "MFC PlugIn" );

var pluginIndex = [];

for ( var i = 0; i < pluginList.length; i++ ) {
    pluginIndex[i] = sysInfo.search( pluginList[i] );
    // $.writeln( pluginList[i] + " = " + pluginIndex[i] );
    if ( pluginIndex[i] == -1 ) {
        errors++;
        fileLog.writeln( "Plug in not found: " + pluginList[i] );
    }
    else if ( pluginIndex[i] > failStart && pluginIndex[i] < failEnd ) {
        errors++;
        fileLog.writeln( "pluginIndex[i] > failStart && pluginIndex[i] < failEnd " +  pluginList[i] );
    }
}

fileLog.close();

if (errors && ! BringToFront() ) {
	fileLog.execute();
}

//     1) " FAIL" for failures
//     2) " PASS" for test results OK
//     3) "  BUG" for known bugs, have the file name give the bug number
//     4) "ERROR" this comes from the harness if the script barfed/exception,

if (errors == 0) {
	errors = ' PASS';
} else {
	errors = ' FAIL';
}
	
LogMessage(errors + "\n");

if ( typeof gHarness == "undefined" || gHarness.showAlerts ) {
	alert( errors );
}

return errors;
}

function LogMessage( inMessage ) {
  if ( BridgeTalk.isRunning( "estoolkit" ) )
    $.write( inMessage );
}

function BringToFront( ) {
    if ( typeof gHarness == "undefined" || typeof gHarness.bringToFront == "undefined" ) {
        return false;
    } 
    return gHarness.bringToFront;
}

// end FindPluginInSystemInfo.jsx

You could use UPIA to “list all”: https://helpx.adobe.com/creative-cloud/help/working-from-the-command-line.html

Hello, these options are not suitable as I am trying to do these checks from Javascript

Yes, it looks impressive, today I will analyze your code in more detail, try to rewrite it for my system and understand in more detail what is happening here

I figured out a way to do this

I get access to the file system and look in standard folders for files where plugins can be located, I get an array of plugin names, and then I look in this array for the plugin I need

Here in the example I showed for a Mac, I have the same method for Windows, it’s exactly the same, only the paths are different

Also, if necessary, you can modify the system and accept another path that the user specifies

async getPluginsListMacOS() {
    const photoshopVersion = host.version.split('.')[0] - 1;

    const folders = [
      'file:///Library/Application%20Support/Adobe/Plug-Ins/CC',
      `file:///Applications/Adobe%20Photoshop%2020${photoshopVersion}/Plug-ins`,
    ];

    let allPlugins = [];
    for (const folder of folders) {
      const plugins = await this.getPluginsFromFolder(folder);
      allPlugins = allPlugins.concat(plugins);
    }

    return allPlugins;
  }

  async getPluginsFromFolder(folderUrl: string) {
    try {
      const folder = await localFileSystem.getEntryWithUrl(folderUrl);
      if (folder.isFolder) {
        const entries = await folder.getEntries();
        return entries.map((entry) => entry.name);
      }
    } catch (err) {
      console.warn(`Failed to access the folder: ${folderUrl}`, err);
    }
    return [];
  }