Script n00b question

General Discussion of Scripting for Adobe Bridge

Moderators: Tom, Kukurykus

nsklobovsky

Script n00b question

Post by nsklobovsky »

Hi everybody!

I need to be able to send the currently selected objects in Bridge (CS/CS2) (both files and folders are OK) to an external app of mine, like that:

myapp.exe "file1" "file2" ... "fileN",

where "fileX" is a fully specified name fo the selected file.

I'd like to be able to have my command "Send to XXX" in two places:
1) in Bridge's File menu
2) in Bridge's context menu of selected files

Say, after "Open in camera RAW" in both cases.

I'm having trouble with Bridge scripting as to where to start.
I have programming experience, but this scripting thus far was not my bag.
I played with extended toolkit, browsed through bridge and photoshop scripting guides, but with not a lot of luck thus far...

Do I need to have one script, or do I need to have an "installer" separate and "sender" separate? Do I need some special library?

The whole task seems like a scripting 101, but for some reason I can't figure it out...


Any pointers, hints, and samples would be greatly appreciated....!

Thanks!
Mike Hale

Script n00b question

Post by Mike Hale »

You will have to edit this for your app, but this should work when edited if installed in the startup scripts folder.

Code: Select all$.level = 0;
if ( BridgeTalk.appName == "bridge" )  { // only load into bridge

   var sendToXXX = {}; // namespace for this script
   sem ={};
   try {
      sendToXXX.scriptInfo = new ScriptManager.ScriptInfo();
      sendToXXX.scriptInfo.set( "name", "Send To XXX" );
      sendToXXX.scriptInfo.set( "description", "Creates a batch file for external app" );
      sendToXXX.scriptInfo.set( "help", "Select image files in Bridge, select the Tools->Sent to XXX" );
      sendToXXX.scriptInfo.set( "author", "Michael Hale" );
      sendToXXX.scriptInfo.set( "company", "" );
      sendToXXX.scriptInfo.set( "copyright", "" );
      sendToXXX.scriptInfo.set( "version", "0.1.0" );
      sendToXXX.scriptInfo.set( "contact", "" );
      sendToXXX.scriptInfo.set( "date", "10-07-2006" );
      sendToXXX.scriptInfo.set( "website", "" );
   } catch ( e ) {
   };
   
   //
   // Exec
   // From Xbytor bb/viewtopic.php?t=344
   Exec = function(app){
     this.app = app;         // A File object to the application
     this.tmp = Folder.temp; // You can use a different folder here
   };

   Exec.prototype.toCommandStr = function(args) {
     var str = '';

     if (this.app) {
       str = '\"' + this.app.fsName + '\"'; // the app
     }

     if (args) {
       // if a file or folder was passed in, convert it to an array of one
       if (args instanceof File || args instanceof Folder) {
         args = ['\"' + args+ '\"'];
       }

       // if its an array, appened it to the command (could use Array.join)
       if (args.constructor == Array) {
         for (var i = 0; i < args.length; i++) {
           str += ' ' + args;
         }
       } else {
         // if its something else (like a prebuilt command string), just append it.
         str += ' ' + args.toString();
       }
     }
     return str;
   };

   Exec.prototype.getBatName = function() {
     var nm = '';
     var ts = new Date().getTime();

     if (this.app) {
       nm = this.tmp + '/' + this.app.name + '-' + ts + ".bat";
     } else {
       nm = this.tmp + "/exec-" + ts + ".bat";
     }
     return nm;
   };

   Exec.system = function(cmd, timeout) {
     var ts = new Date().getTime();
     var e = new Exec();
     var outf = new File(e.tmp + "/exec-" + ts + ".out");
     e.executeBlock(cmd + "> \"" + outf.fsName + '\"', 5000);

     outf.open("r");
     var str = outf.read();
     outf.close();
     outf.remove();
     return str;
   };

   Exec.prototype.execute = function(argList) {
     var str = this.toCommandStr(argList);
     var bat = new File(this.getBatName());
     bat.open("w");
     bat.writeln(str);
     bat.writeln("del \"" + bat.fsName + "\" >NUL");
     bat.close();
     bat.execute();
   };

   Exec.prototype.block = function(semaphore, timeout) {
     if (timeout) {
       var parts = 10;            // wait for 1/10 of the timeout in a loop
       timeout = timeout / parts;

       while (!semaphore.exists && parts) {
         $.sleep(timeout);
         parts--;
       }

       if (!parts && !semaphore.exists) {
         throw "Timeout exceeded for program " + this.app.name;
       }
     }
   };

   Exec.prototype.executeBlock = function(argList, timeout) {
     var str = this.toCommandStr(argList);

     var bat = new File(this.getBatName());
     var semaphore = new File(bat.toString() + ".sem")

     bat.open("w");
     bat.writeln(str);
     bat.writeln("echo Done > \"" + semaphore.fsName + '\"');
     bat.writeln("del \"" + bat.fsName + "\" >NUL");
     bat.close();
     bat.execute();

     try {
       this.block(semaphore, timeout);
     } finally {
       semaphore.remove();
     }
   };
   
   function quoteString( str )  {
      var s = new String( '"'+str+'"' );
      return s;      
   };
   
   sendToXXX.run = function(){
      $.level = 2;
   
      var XXXRef = 'C:\\XXX program\\XXX.exe';
      var XXX = new Exec();
      var sels = app.document.selections;
      if(sels<1){return;}      
      var temp = new Array;
      temp.push(quoteString(XXXRef));
      for( var i = 0; i < sels.length; i++ ) {
         if ( sels[ i ].type == 'file' || sels.type == 'folder') {
            temp.push(quoteString(sels.spec.fsName));
         };
      };
      XXX.execute(temp);
   };         
         
      createMenu( "command", "Send to XXX", "at the end of tools",  "sendToXXX", sendToXXX.run );
      try {
         ScriptManager.reportLoading( sendToXXX.scriptInfo );
      } catch ( e ) {
      };
};
nsklobovsky

Script n00b question

Post by nsklobovsky »

Mike Hale wrote:You will have to edit this for your app, but this should work when edited if installed in the startup scripts folder.


I *do* appreciate your time and effort!
I'll give this a try as soon as I figure out what it's doing:-)

Thank you *VERY* much!
Mike Hale

Script n00b question

Post by Mike Hale »

What it does is take the selected images in Bridge and puts the full Windows path in quotes into an array. It adds the Windows path of the external app to the start of that array.

It then uses Xbytor's Exec object to create and execute a .bat file using the array as the command line string.

It also add a menu item in the Tools menu

Mike
nsklobovsky

Script n00b question

Post by nsklobovsky »

I tried your script.
Got the following problems: (PS CS2, Win XP, all the latest updates for both)
The following line produced an error saying "no such function createMenu":

Code: Select allcreateMenu( "command", "Send To XXX", "at the end of tools",  "sendToXXX", sendToXXX.run );

I tried to replace it with the following two lines of code (based on scripting bridge.pdf):

Code: Select allvar cmdSendToXXX = new MenuElement( "command", "Send to XXX", "at the end of tools",  "cmdSendToXXX");
cmdSendToXXX.OnSelect =  function() { sendToXXX.run };

This one created the menu item (yay!), but, alas, it didn't do anything upon execution...

I even tried to put an alert in the OnSelect handler jsu to see if it works - no effect. It's not called.


What am I doing wrong?

Second problem.

The scripting bridge pdf says that such script should be placed at:
In Windows®, the startup folders are:
%APPDATA%\Adobe\StartupScripts
%APPDATA%\Adobe\StartupScripts\bridge\version
I tried to copy it to
Code: Select allC:\Documents and Settings\%MY_USER_NAME_HERE%\Application Data\Adobe\StartupScripts
but it didn't even create the menu (as opposed to when ran from ExtendedScriptToolkit), so I recon it didn't run at all.
I also tried All Users - same effect.

Same question - what am I doing wrong?

Thank you very much for your help!
Mike Hale

Script n00b question

Post by Mike Hale »

Sorry, you will also need the Adobe Library scripts bb/viewtopic.php?p=302 I have had them so long I forgot that I used a function from AdobeLibrary1.

Here is the Windows path where I put my start-up scripts and they work from that folder C:\Program Files\Common Files\Adobe\StartupScripts.

With my script and the library scripts in the startup folder, it should only need the external app path edited to run. Note that as these are start-up scripts, Bridge needs to be closed or restarted before they can be used.

BTW, the basic shell for my script was borrowed from Bob Stuckey's OpenClose script that can be found in the same post with the link to the Adobe Libs.

Mike
nsklobovsky

Script n00b question

Post by nsklobovsky »

I found AdobeLibrary 1, 2 and Script Manager, put them all to Common files... - and it seems to work now!

Mike, I truly appreciate your help!!

Now with the working base script I can try to extend it myself:-)

Thank you so very much again!
scripting101

Script n00b question

Post by scripting101 »

Hi,

This script is very inetresting but I need to open remote files in bridge using Photoshop. That is Bridge points to a remote file (residing on another web server) and I need to be able to pull it out and open it in my custom app.

any ideas on how I can go about doing that?
Mike Hale

Script n00b question

Post by Mike Hale »

Does you custom app take command line arguments? And how did you get Bridge to browse a web server?