Open web page in After Effects with ExtendScript - extendscript

This may be a simple one but I can't figure it out. How can I open a web page in the main browser from extendscript as I would do with window.open() in Javascript?
I am targeting After Effects and would like it to work on both OS X and Windows.

In After Effects you can simply do it using the system object, as Dirk mentioned. However you need several things for that:
checking that the script can access the network:
if (app.preferences.getPrefAsLong("Main Pref Section", "Pref_SCRIPTING_FILE_NETWORK_SECURITY") != 1)
{
alert("Please tick the \"Allow Scripts to Write Files and Access Network\" checkbox if Preferences > General");
// Then open Preferences > General to let people tick the checkbox
app.executeCommand(2359);
// Here you should check again if they ticked it, and choose to continue or stop ...
}
checking of the OS:
var os = system.osName;
if (!os.length)
{
// I never remember which one is available, but I think $.os always is, you'll have to check
os = $.os;
}
app_os = ( os.indexOf("Win") != -1 ) ? "Win" : "Mac"
os-dependent system calls:
var url = "http://aescripts.com";
if ( app_os == "Win" )
{
system.callSystem("explorer " + url);
}
else
{
system.callSystem("open " + url);
}

Provided you have access to CSInterface.js:
cep.util.openURLInDefaultBrowser("http://www.google.com")

One application independent way is to write an operating system's representation of the URL into a file, then execute() the file.
On the Mac that would be a .webloc file. The underlying format is "plist binary", if you prefer to generate xml, create a sample webloc by drag&drop from the browser address and convert it:
plutil -convert xml1 ~/Desktop/sample.webloc
To invoke that webloc, run the ExtendScript
File("~/Desktop/sample.webloc").execute()

You can do anything on your local computer - commandline and anything else in a VBS file, and you can launch a vbs file from javascript like this:
function RunScriptVBS(whatscriptname){
app.doScript(File(whatscriptname), ScriptLanguage.VISUAL_BASIC);
}
Here is your vbs script:
Dim objShell
Set objShell = CreateObject("WScript.shell")
objShell.Run ("http://www.somewhere.com")
set objShell = nothing

The scope of the question apparently has been refined to After Effects (AE), so I add another answer specific to that application.
On my Machine AE CS6 does not produce an object model file for display by the ExtendScript Toolkit. Please retry it yourself, the object model viewer is in the help menu of ESTK.
Anyway, the ESTK data browser does works. If you target AE, you'll see a couple of objects and classes. Eventually check some more menu items in the databrowser panel flyout menu. I had a deeper look at the app object itself (no openUrl() there) and also found a "system" object. Expand that and you see several interesting methods.
The following script opens a URL on the Mac. I have not tried Windows, maybe it is even the same.
system.callSystem("open http://www.google.com")
As this is the first time I launched AfterEffects, I might have missed better ways.

Related

I am having problems trying to display a RTF data file in a rich text edit control in a MFC dialog

I saw a discussion here about displaying a RTF file in a rich text edit control. Maybe what I am trying to do it too much.
In my dialog class I define a static method:
static DWORD CALLBACK MyStreamInCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb)
{
std::ifstream* pFile = (std::ifstream*)dwCookie;
pFile->read((char*)pbBuff, cb);
return 0;
}
In my dialog OnInitDialog class I try to display the data:
std::ifstream File("d:\\RevisionHistoryTest.rtf");
EDITSTREAM es = { 0 };
es.dwCookie = (DWORD)&File;
es.pfnCallback = MyStreamInCallback;
::SendMessage(m_rtfEdit, EM_STREAMIN, SF_RTF, (LPARAM)&es);
Now, here is a link to a sample project. I don't know where I can put this project in the long term, but my DropBox will do for now. The project does not include the RTF file. This is how I created it:
I went to the following URL in a browser.
I selected all the Revision History content and pasted it into a Microsoft Word file.
I copied the Microsoft Word content and pasted it into a WordPad session and saved it.
Example:
Interestingly, when I subsequently open my RTF file in WordPad I get a popup message:
If I select Unblock then it still opens in the editor. I assume that is because all of the images must still be linked to those on my website. And I think this is related to the issue with my test project, because this is what I see:
I get no errors or anything. It just reads the first line and stops.
I am trying to find the easiest way to display my HTML history in a RTF window.
My original intention was to use a CHtmlView control instead (makes sense to do that) and directly read my Revision History file from the internet. But my help system is designed to permanently show the contents pane on the left. This is why I thought that RTF might be a suitable alternative. But struggling with it.
Update
Based on the comments made about 64 bit builds I located this tutorial which works for both 32 bit and 64 bit. They both display "Revision History" only.
BOOL FillRichEditFromFile(HWND hwnd, LPCTSTR pszFile)
{
BOOL fSuccess = FALSE;
HANDLE hFile = CreateFile(pszFile, GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
EDITSTREAM es = { 0 };
es.pfnCallback = MyStreamInCallback;
es.dwCookie = (DWORD_PTR)hFile;
if (SendMessage(hwnd, EM_STREAMIN, SF_RTF, (LPARAM)&es) && es.dwError == 0)
{
fSuccess = TRUE;
}
CloseHandle(hFile);
}
return fSuccess;
}
And in OnInitDialog:
FillRichEditFromFile(m_rtfEdit.GetSafeHwnd(), _T("d:\\RevisionHistoryTest.rtf"));
But my initial issue still remains.
Update
I had forgotten to set the control to multiline! That was part of the issue:
At least all of the text is visible now. Just not the images. And I don't like the way some of the links are displayed.
I have been able to edit the file and bring the indents over to the left to make it look better. But images still won't show.
Update
As a workaround to this I realised that I could simply duplicate my HTML Revision History as a standalone page. Then I can use CHtmlView:
The benefit is that the display is consistent wit what the user sees in the help system.

HWND handle being returned via FindWindowW differs from top-level parent

I'm trying to create a utility that will selectively hide and show windows based on pre-assigned hotkeys and I'm working with the Windows API code.
I use a FindWindowW call to get a handle to a window as a test (in my case, a window with the text "Calculator - Calculator", which matched an open calculator window) and use that handle in a ShowWindow function.
Code below:
var user32path = 'C:\\Windows\\System32\\user32.dll';
function TEXT(text){
return new Buffer(text, 'ucs2').toString('binary');
}
var user32 = new FFI.Library(user32path, {
'FindWindowW': ['int', ['string', 'string']],
'ShowWindow': ['int', ['int', 'int']],
'ShowWindowAsync': ['int', ['int', 'int']],
'FindWindowExW': ['int', ['int', 'int', 'string', 'string']],
'BringWindowToTop': ['int', ['int']],
'GetActiveWindow': ['int', ['int']]
var handle = user32.FindWindowW(null,TEXT("Calculator ‎- Calculator"));
user32.ShowWindow(
handle, 'SW_Hide');
//associatedWindowHandle is a manually-created variable with the Spy++ variable.
//The Spy++ doesn't match and I'm not sure why.
user32.ShowWindowAsync(activeHandle, 'SW_Hide');
var pruneLength = Object.keys(prunedData).length;
for (let i = 0; i < pruneLength-1; i++){
if (Object.entries(prunedData)[i][1] === hotkey){
for(let j = 1; j <= prunedData.assocWindows.length; j++){
let associatedWindow = Object.entries(prunedData)[i+1][j].toString();
let associatedWindowHandle = parseInt(associatedWindow);
user32.ShowWindowAsync(associatedWindowHandle, 'SW_Hide');
user32.BringWindowToTop(associatedWindowHandle[i+1][j]);
}
}
}
2 main issues:
When I try hiding and/or minimizing the open calculator window, I can't seem to show it again when clicking on it. the preview image disappers and I notice a "Process Broker" is thrown.
I can't seem to actually find the window handle given with tools like Spy++, which makes it somewhat hard to debug to see if I need to grab a different handle. The parent-level calculator window's handle doesn't seem to match, and I verified that it was the same tool.
I'd also like to be pointed to some decent resources to help self-educate on this so I can better troubleshoot this in the future.
Many thanks!
Firstly, I'd echo Hans Passant's remarks that you're probably better off not trying to so this with a UWP app like Calculator, but then again these apps are not going to go away so perhaps you might want to try anyway.
The shell doesn't appear to appreciate you trying to hide a UWP app (Win32 apps work fine though, go figure). As you have observed, it's icon remains visible in the toolbar but behaves strangely while the window is hidden. So, short version, don't do that.
Instead, try this:
PostMessage (hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
Then things work a lot better, although the user can still undo all your good work by reopening the window of course.
As for Spy++, I have no trouble locating the top-level window of a UWP app using the 'Finder tool' (Menu -> Search -> Find Window). You just have to walk a couple of levels up the window hierarchy afterwards until you get to the one you really want.
Spy++ seems not to be able to log messages being sent to such a window however, see (shameless plug): Why can't Spy++ see messages sent to UWP apps?. I plan to look into this a bit more when I have time.
Finally, what do you mean by 'a "Process Broker" is thrown' please? I don't understand that comment. There's something called RuntimeBroker, which shows up in Process Explorer and appears to be connected with UWP apps in some way, but I don't know if that's what you mean and and I don't know anything about it even if you did.

How do I open a file with my application?

Ok, you know how in programs like Microsoft Excel, or Adobe Acrobat Reader you can click on a file in explorer and it will open with the associated program. That's what I want my application to do. Now, I know how to set up the file associations in Windows so that it knows the default program for each extension. My question is how do I get my application to open the file when I double click the file.
I've searched the web using google, I've searched the msdn site, and I've searched several forums including this one but I haven't found anything that explains how to accomplish this. I'm guessing it has something to do with the parameters of the main method but that's just a guess.
If someone can point me in the right direction I can take it from there. Thanks in advance for your help.
Shane
Setting up the associations in windows will send the filename to your application on the command line.
You need to read the event args in your applications main function in order to read the file path and be able to open it in your application.
See this and this to see how to access the command line arguments in your main method.
static void Main(string[] args)
{
System.Console.WriteLine("Number of command line parameters = {0}", args.Length);
foreach (string s in args)
{
System.Console.WriteLine(s);
}
}
When you open the file, with associations set as you described, your application will be started with the first argument containing the filepath to your file.
You can try this out in a simple way by printing out the args from your main method, after you open your application by clicking on the associated file. The 0th element should be the path to your file.
Now, if you successfully reached this point, the all you need to do now is read the contents of the given file. I'm sure you'll find more than plenty of resources here on how to do that.
I guess this is what you are looking for:
FileInfo fi = new FileInfo(sfd.FileName); //the file you clicked or saved just point
//to the right file location to determine
//full filename with location info
// opening file
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = #fi.FullName;
startInfo.WindowStyle = ProcessWindowStyle.Normal;
Process process = new Process();
process.StartInfo = startInfo;
process.Start();
You will need to create registry-keys for your file-extension. This page describes well, which keys you'll need to set (see «3. How do I create file associations?»).

How to attach mouse event listeners to embedded nsIWebBrowser in C++

I've embedded an nsIWebBrowser in my application. Because I'm just generating HTML for it on the fly, I'm using OpenStream, AppendToStream, and CloseStream to add content. What I need is to add event listeners for mouse movement over the web browser as well as mouse clicks. I've read documentation and tried lots of different things, but nothing I have tried has worked. For instance, the code below would seem to do the right thing, but it does nothing:
nsCOMPtr<nsIDOMWindow> domWindow;
mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
if (!mEventTarget) {
mEventTarget = do_QueryInterface(domWindow);
if (mEventTarget)
mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseover"), (nsIDOMEventListener *)mEventListener, PR_FALSE);
}
Perhaps it isn't working because this is run during initialization, but before any content is actually added. However, if I add it during AppendStream, or CloseStream, it segfaults.
Please tell me a straightforward way to do this.
Well, here's the answer:
nsCOMPtr<nsIDOMEventTarget> cpEventTarget;
nsCOMPtr<nsIDOMWindow> cpDomWin;
m_pWebBrowser->GetContentDOMWindow (getter_AddRefs(cpDomWin));
nsCOMPtr<nsIDOMWindow2> cpDomWin2 (do_QueryInterface (cpDomWin));
cpDomWin2->GetWindowRoot(getter_AddRefs(cpEventTarget));
rv = cpEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
m_pBrowserImpl, PR_FALSE);

Flash trace output in firefox, linux

I'm developing an applications which I've got running on a server on my linux desktop. Due to the shortcomings of Flash on Linux (read: too hard) I'm developing the (small) flash portion of the app in Windows, which means there's a lot of frustrating back and forth. Now I'm trying to capture the output of the flash portion using flash tracer and that is proving very difficult also. Is there any other way I could monitor the output of trace on linux? Thanks...
Hope this helps too (for the sake of google search i came from):
In order to do trace, you need the debugger version of Flash Player from
http://www.adobe.com/support/flashplayer/downloads.html (look for "debugger" version specifically - they are hard to spot on first look)
Then an mm.cfg file in your home containing
ErrorReportingEnable=1 TraceOutputFileEnable=1 MaxWarnings=50
And then you are good to go - restart the browser. When traces start to fill in, you will find the log file in
~/.macromedia/Flash_Player/Logs/flashlog.txt
Something like
tail ~/.macromedia/Flash_Player/Logs/flashlog.txt -f
Should suffice to follow the trace.
A different and mind-bogglingly simple workaround that I've used for years is to simply create an output module directly within the swf. All this means is a keyboard shortcut that attaches a MovieClip with a textfield. All my traces go to this textfield instead of (or in addition to) the output window. Over the years I've refined it of course, making the window draggable, resizable, etc. But I've never needed any other approach for simple logging, and it's 100% reliable and reusable across all platforms.
[EDIT - response to comment]
There's no alert quite like javascript's alert() function. But using an internal textfield is just this simple:
ACTIONSCRIPT 1 VERSION
(See notes at bottom)
/* import ExternalInterface package */
import flash.external.*;
/* Create a movieclip for the alert. Set an arbitrary (but very high) number for the depth
* since we want the alert in front of everything else.
*/
var alert = this.createEmptyMovieClip("alert", 32000);
/* Create the alert textfield */
var output_txt = alert.createTextField("output_txt", 1, 0, 0, 300, 200);
output_txt.background = true;
output_txt.backgroundColor = 0xEFEFEF;
output_txt.selectable = false;
/* Set up drag behaviour */
alert.onPress = function()
{
this.startDrag();
}
alert.onMouseUp = function()
{
stopDrag();
}
/* I was using a button to text EI. You don't need to. */
testEI_btn.onPress = function()
{
output_txt.text = (ExternalInterface.available);
}
Notes: This works fine for AS1, and will translate well into AS2 (best to use strong data-typing if doing so, but not strictly required). It should work in Flash Players 8-10. ExternalInterface was added in Flash 8, so it won't work in previous player versions.
ACTIONSCRIPT 3 VERSION
var output_txt:TextField = new TextField();
addChild(output_txt);
output_txt.text = (String(ExternalInterface.available));
If you want to beef it out a bit:
var alert:Sprite = new Sprite();
var output_txt:TextField = new TextField();
output_txt.background = true;
output_txt.backgroundColor = 0xEFEFEF;
output_txt.selectable = false;
output_txt.width = 300;
output_txt.height = 300;
alert.addChild(output_txt);
addChild(alert);
alert.addEventListener(MouseEvent.MOUSE_DOWN, drag);
alert.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
output_txt.text = (String(ExternalInterface.available));
function drag(e:MouseEvent):void
{
var alert:Sprite = e.currentTarget as Sprite;
alert.startDrag();
}
function stopdrag(e:MouseEvent):void
{
var alert:Sprite = e.currentTarget as Sprite;
alert.stopDrag();
}
[/EDIT]
If you only need the trace output at runtime, you can use Firebug in Firefox and then use Flash.external.ExternalInterface to call the console.log() Javascript method provided by Firebug.
I've used that strategy multiple times to a large degree of success.
Thunderbolt is a great logging framework with built-in firebug support.
I use the flex compiler on linux to build actionscript files, [embed(source="file")] for all my assets including images and fonts, I find actionscript development on linux very developer friendly.
Then again, I'm most interested in that flash has become Unix Friendly as aposed to the other way around :)
To implement FlashTracer, head to the following address and be sure you have the latest file. http://www.sephiroth.it/firefox/flashtracer/ . Install it and restart the browser.
Head over to adobe and get the latest flash debugger. Download and install the firefox version as FlashTracer is a firefox addition.
Now that firefox has the latest flash debugger and flash tracer we need to locate mm.cfg
Location on PC: C:\Documents and Settings\username
Inside of mm.cfg should be:
ErrorReportingEnable=1
TraceOutputFileEnable=1
MaxWarnings=100 //Change to your own liking.
Once that is saved, open firefox, head to the flash tracer window by heading to tools > flash tracer. In the panel that pops up there is two icons in the bottom right corner, click the wrench and make sure the path is set to where your log file is being saved. Also check to see that flash tracer is turned on, there is a play/pause button at the bottom.
I currently use this implementation and hope that it works for you. Flash Tracer is a little old, but works with the newest versions of FireFox. I am using it with FireFox 3.0.10.

Resources