Search code examples
c#adobeextendscript

C# and ExtendScript for batch processing of .incx files


I have a ton of .incx text documents clustered into their own individual subfolders that I need to iterate through and convert to plaintext as part of a C# winform app I've created. I have the latest version of InCopy and the ExtendScript Toolkit, and a .jsx script that works great to quietly and quickly create my plaintext files.

My problem/question is that there isn't much guidance on how to best launch this from within a C# class in a running 3rd party app, sending in relevant info. When I run my .jsx script, I need to send it a target folder from my app where it can find the .incx files.

The target folder(s) will be dynamic depending on other previous actions in my app.

I've found a few vague hints to solutions on Adobe's forums involving additional .vbs files and/or external temp files to hold arguments, but they're all pretty dated, so I thought I'd ask and see if anyone knew of a contemporary method. If anything is unclear, I'll respond right away to clarify.


Solution

  • Through a lot more Googling and my own trial and error, I have found my answer.

    The best way I can find is to do all of my InCopy scripting in VBS and then use a Process instance to send in my arg(s) with cscript.

    Example C#:

    Process myScriptProc = new Process();
    myScriptProc.StartInfo.FileName = @"cscript";
    myScriptProc.StartInfo.WorkingDirectory = rootDir + "\\";       // rootDir being the path where my vbs lives
    myScriptProc.StartInfo.Arguments = "MyScript.vbs " + filesPath; // filesPath is the arg sent to the script
    myScriptProc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    myScriptProc.Start();
    myScriptProc.WaitForExit();
    myScriptProc.Close();
    

    MyScript.vbs

    main
    Function main() 
        Set myInCopy = CreateObject("InCopy.Application.CC.2015")
        Set obj = CreateObject("Scripting.FileSystemObject")
        myInCopy.ScriptPreferences.UserInteractionLevel = 1699640946    
        myFormat = 1952412773
        myExtension = ".txt"
        Set objFSO = CreateObject("Scripting.FileSystemObject") 
        objStartFolder = WScript.Arguments(0)   
        Set objFolder = objFSO.GetFolder(objStartFolder)
        Set colFiles = objFolder.Files
        For Each x In colFiles
        If LCase(objFSO.GetExtensionName(x.name)) = "incx" Then
                thisDoc = x
                Set myDoc = myInCopy.open(thisDoc)
                Set myStory = myInCopy.ActiveDocument.Stories.Item(1)
                parts = split(x.Name, ".")
                myFilePath = objStartFolder & "/" & parts(0) & myExtension  
                myStory.Export myFormat, myFilePath
                myDoc.close()
                obj.DeleteFile(thisDoc)
            End If
        Next
        myInCopy.ScriptPreferences.UserInteractionLevel = 1699311169
    End Function
    

    I rewrote my JavaScript file in VBScript because judging from the tumbleweeds blowing through the Adobe forums, I was never going to get any answers as to why their documentation examples for calling DoJavaScriptFile produce object missing method errors.

    The biggest hurdle I ran into after redoing my script in VB was that you have to use the super-secret enumerated decimal values for Adobe-specific things if you run the scripts externally. If you look at MyScript.vbs you'll see a few instances of what look like random 10 digit values. Those come from here:

    http://jongware.mit.edu/idcs5js_html_3.0.3i/idcs5js/index_Enum%20Suite.html

    Bless the guy who created that resource, because I couldn't find that information in any of Adobe's documentation to save my life.

    TL;DR: If you're trying to automate using processes and scripts that run outside an Adobe app, do everything in VBScript, and beware the mystery decimal enumerations.

    useless footnote: MyScript.vbs here reads all *.incx files from the passed in directory, exports as plain .txt (with the same filename, into the same dir), and deletes the original.