About two years back, Notre Poubelle was looking for a way to get ahold
of ShDocVw.ShellWindows via script. Now ignoring the fact that it is
essentially identical to CreateObject("Shell.Application").Windows,
this is an interesting problem because the class id was known, but that
was all.

There was a clever idea by Alexander Mueller, which was tested out,
that maybe it was possible to use IE for this, but it failed because of
the security blanket that IE surrounded the object with. However,
here's a working solution, which extends the original idea. The key
idea is that after having IE create the object, we take it away from IE
so the security restrictions will no longer exist. Even if it wasn't
clear to IE that our app could freely muck with it, it should be clear
to everybody that our VB app/script is free to go about it's own
business on its own time.


Dim ie, Tname, oWins, win, text
Set ie=CreateObject("InternetExplorer.Application")
ie.Navigate2("about:blank")
ie.Document.open
ie.Document.write "<object id=sw classid='clsid:" & _
"9BA05972-F6A8-11CF-A442-00A0C90A8F39'></object>"
ie.Document.close
Set oWins = ie.document.parentWindow.sw 'transfer object
ie.Document.parentWindow.execScript "window.sw=null" 'paranoia
ie.quit 'more of same
msgbox "oWins: " & typename(oWins)
'This loop prints out something on each instance of IE / Explorer
For each win in oWins
Tname = typename(win.document)
if mid(Tname,1,12)="HTMLDocument" Then
text = win.document.title
if text<>"" then text = "Title: " & text & vbCrLF
MsgBox text & "url: " & win.document.location
Else
MsgBox "Folder: " & win.locationURL
End If
Next

This code was adapted from:
http://groups.google.com/group/microsoft.public.scripting.jscript/browse_frm/thread/cb42d8b604de28eb/


The reason I said ShDocVw.ShellWindows was essentially the same as
CreateObject("Shell.Application").Windows was because of hooking event
handlers up. For example, in a VB project, if I do
Dim WithEvents ogSW As SHDocVw.ShellWindows
Set ogSW = New SHDocVw.ShellWindows
then I can receive events of IE/Explorer creations/destruction via:
Private Sub ogSW_WindowRegistered(ByVal lCookie As Long)
and
Private Sub ogSW_WindowRevoked(ByVal lCookie As Long)
but this approach does not work with the other.

Enjoy,
Csaba Gabor from Vienna

Re: ShDocVw.ShellWindows vs. CreateObject("Shell.Application").Windows by mr_unreliable

mr_unreliable
Fri Aug 19 11:02:05 CDT 2005

hi Csaba from Vienna,

Always a pleasure to read about your side-trips into scripting exotica.

cheers, jw

Re: ShDocVw.ShellWindows vs. CreateObject("Shell.Application").Windows by mr_unreliable

mr_unreliable
Mon Aug 22 15:27:37 CDT 2005

This is a multi-part message in MIME format.
--------------090301060302080607050008
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Csaba, you don't need to take a side-trip thru IE to get at
the IShellWindows interface.

You may get at it directly (or any other object not having
a progid), by using the wsf file format, and specifying your
object tag that way.

cheers, jw
____________________________________________________________

You got questions? WE GOT ANSWERS!!! ..(but,
no guarantee the answers will be applicable to the questions)

p.s. the attached script's extension was changed to txt,
to avoid that slanderous diagnostic "Malicious Script Detected".

--------------090301060302080607050008
Content-Type: text/plain;
name="wshUsingWSFObjectTag_toInstantiate_IShellWindows.wsf.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="wshUsingWSFObjectTag_toInstantiate_IShellWindows.wsf.txt"

<?XML version="1.0" standalone="yes" encoding="iso-8859-1" ?>
<job id="testInstantiatingSHDovVu">
<object id="oSDV" classid="clsid:9BA05972-F6A8-11CF-A442-00A0C90A8F39" />

<script language="VBScript" >
<![CDATA[

' test using wsf file object tag to instantiate shdocvu from guid, jw 21Aug05
' (note: the primary value of this is that it allows for accessing
' an interface whose class id is registered, but the progid is not)..

Dim oWins ' as object (IShellWindows interface)
Dim win ' as window object
Dim sTypName, sReport ' as strings

Set oWins = oSDV ' rename object
MsgBox "object typename: " & TypeName(oWins) ' expect IShellWindows

' this loop enumerates each instance of IE / Explorer
For Each win in oWins
sTypName = TypeName(win.document)
if Mid(sTypName,1,12)="HTMLDocument" then
sReport = win.document.title
if (sReport <> "") then sReport = "Title: " & sReport & vbCrLf
MsgBox sReport & "url: " & win.document.location, vbInformation, _
" Enum Wins: found IE instance "
Else
MsgBox "Folder: " & win.locationURL, vbInformation, _
" Enum Wins: found folder "
End If
Next ' win

MsgBox("quitting now")
WScript.Quit

]]>
</script>
</job>

--------------090301060302080607050008--

Re: ShDocVw.ShellWindows vs. CreateObject("Shell.Application").Windows by Csaba

Csaba
Tue Aug 23 09:54:18 CDT 2005

mr_unreliable wrote:
> Csaba, you don't need to take a side-trip thru IE to get at
> the IShellWindows interface.
>
> You may get at it directly (or any other object not having
> a progid), by using the wsf file format, and specifying your
> object tag that way.

Hi JW,

Thanks for that .wsf example. But is there anyway to move that
"header stuff" into a .vbs file? The reason that I ask is that the
stuff I am doing now is mainly for MSScriptControl.ScriptControl (and
as I understand it, I can't add objects as you are declaring with your
<objects ...> tag).

Csaba


Re: ShDocVw.ShellWindows vs. CreateObject("Shell.Application").Windows by mr_unreliable

mr_unreliable
Tue Aug 23 11:05:44 CDT 2005

Csaba, since you are now mentioning the script control, I am
going to assume that the host language is visual basic (or
more specifically "classic" vb5 or vb6)...

If that is the case, then you don't need scripting (or IE) to
instantiate your object, you can do it in vb, and then pass
that reference into the script control for use by your script.

First off, set a reference in your vb project to the
shdocvu.dll.

Then this is the code you will need to pass the
(IShellWindows interface) object into the script
control:

--- <snip> ---
Dim oSDV As SHDocVw.ShellWindows

' create a reference to the IShellWindows interface...
Set oSDV = New SHDocVw.ShellWindows

' pass the reference(s) into the script control...
scScript.AddObject "IShellWindows", oSDV, True
--- </snip> ---

From then on you should be able to use the "oSDV" object
in your script by referring to it as "IShellWindows",
just as if you had created it yourself (er, created it in
the script, that is).

Or, if you find "IShellWindows" too lengthy, you could
use something more simple and direct, such as "oWins"...

cheers, jw
____________________________________________________________

You got questions? WE GOT ANSWERS!!! ..(but,
no guarantee the answers will be applicable to the questions)


Csaba Gabor wrote:
> Hi JW,
>
> Thanks for that .wsf example. But is there anyway to move that
> "header stuff" into a .vbs file? The reason that I ask is that the
> stuff I am doing now is mainly for MSScriptControl.ScriptControl (and
> as I understand it, I can't add objects as you are declaring with your
> <objects ...> tag).
>
> Csaba
>

Re: ShDocVw.ShellWindows vs. CreateObject("Shell.Application").Windows by Csaba

Csaba
Tue Aug 23 14:23:10 CDT 2005

mr_unreliable wrote:
> Csaba, since you are now mentioning the script control, I am
> going to assume that the host language is visual basic (or
> more specifically "classic" vb5 or vb6)...

Sorry, JW. My Bad. I am using the MSScriptControl from PHP. Example:

<?php
$script = new COM("MSScriptControl.ScriptControl");
$script->language = "VBScript";
$script->eval('MsgBox ("Hi Mom")');
?>


I guess I should backup. This post is sort of a side branch to a side
branch of my main problem, but it was interesting in and of its own
right so I figured it merited a post.

Here's the real deal (which may get its own separate post as my
frustration mounts), but just in case...

I've got a Web server (Apache 2.0.53 / PHP 5.1 as module / Win XP Pro,
SP 2). When a request for a certain page comes in, I want to be able
to loop through all instances of IE. The reason for that is that
there's going to be a PHP program running the background and its going
to have a huge data structure in memory and the idea is for the server
PHP scripts (hereafter referred to as CGI PHP even though it is hooked
into Apache as a module) to be able to access the resident PHP script
directly. Now the glue for connecting these two (the resident CLI
(command line) PHP and the server/CGI PHP) is IE. [Note that in the
context of the scenario I am outlining, the resident/CLI PHP is the
data server, while the CGI PHP that runs upon a web request is actually
the client to the data server. However, I will continue to use the
term CLI/resident and CGI PHP to minimize the confusion from the double
use of web/data server/client]

If I use two (or more) instances of CLI php, everyone is happy, the
process works nicely. I have a demo where each CLI PHP instance brings
up its own associated instance of IE (based on a common base title).
Everybody (that is, all the IE's and hence their associated PHPs) finds
each other and as you type anything in any such instance of IE, all the
other instances immediately reflect it. Nifty. Of course the way that
the IEs find each other is through
CreateObject("Shell.Application").Windows

This does not work when one of the PHP instances (we're back to two
now) is a web server script (CGI PHP). Specifically, there ought to be
two ways to connect the two instances of IE. Either the CGI PHP script
should be able to see the (resident) CLI php's IE (via wsCGI =
CreateObject("Shell.Application").Windows) or the CLI PHP should get a
notification of the creation of the CGI PHP's IE =
CreateObject("InternetExplorer.Application") by hooking the
WindowRegistered event of wsCLI =
CreateObject("Shell.Application").Windows

When you try it, the CGI PHP silently fails in looping through the
windows. Furthermore, even though an IE object is created by the CGI
PHP it never registers itself with the shell so that the event in CLI
PHP is never fired. I say that it doesn't register with the shell
because the "cookie" parameter in the event handler is an integer that
is incremented each time a new IE / Explorer window is created.
Bringing up a new IE, subsequent to a hit to the web server, shows an
integer one larger than that with the previous visible IE window.

All this has been a very long winded way of saying that the program
which Apache invokes to handle the request is severly restricted. I
should in theory be able to bypass this restriction by right clicking
Apache in the System Tray and opening services, then right clicking on
Apache there and going to Properties, and then in the Logon section
allowing Apache to interact with the desktop. Didn't work.

So my real question is, is there any way that I can bypass this
restriction, especially on a per page basis? Oh, and it's a VBScript
question because I can shove everything that I just talked about into
the MSScriptControl.ScriptControl and it happens the same way there,
too.

And now you know,
Csaba Gabor from Vienna