Windows Vista Forums
Vista Forums Home Join Vista Forums Donate Vista Tutorials Tags

Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
Register at Vista forums...the world biggest Windows Vista resource Join Vista Forums Now

Go Back   Vista Forums > Microsoft Technical Newsgroups > PowerShell

Non interactive process control manipulation

Update your Vista Drivers Update Your Drivers Now!!
Closed Thread
 
Thread Tools Display Modes
Old 05-19-2008   #1 (permalink)
Bill V.
Guest


 

Non interactive process control manipulation

Hello everyone.

This might be more of a .Net question, but I'm ultimately using powershell,
so I thought I'd start here.

Some time ago, I posted here in trying to figure out a good way of
automating installs and other processes on the computers at my work. (I'm a
PC tech at a Community College). Many educational applications aren't
written with automation in mind, so you end up pressing a lot of buttons in a
GUI to get things done. Part of my challenge was that I wanted something
that would work whether someone was signed into the computer or not. So,
this meant I couldn't use sendkeys, since that required someone to be signed
in and have the application in focus to be able to control it (at least it
worked this way in VBScript when I used it, and it didn't seem like things
had changed any). Ultimately, the method I ended up using is Win32 APIs
called through .Net (which I then was referencing through powershell) where I
used Findwindow, FindwindowEX, and Sendmessage to control the applications
that I couldn't manage any other way. I have a scheduled task that I run
Sunday mornings (around 1:00 am) that does initial installs, and installs any
updated applications since the last run.

For the most part, this worked fine. Generally, I only used canned
keystrokes when I had to, and when I did, things worked well enough. But,
just recently, I've come across some applications that just don't want to
work. Ultimately, I think that the problem comes down to the fact that since
the apps that I'm running are scheduled tasks they don't interact with the
desktop. The reason I've come to this conclusion is that I can run the
script and I see the application running in the process list of the task
manager. However, I can't find the application using Winspector Spy, and
Findwindow doesn't find any windows of the applications. Now, I've run some
other installers this way, and it's worked out, but most of the time these
are self extracting application - so I start one executable, but I end up
manipulating another one, so I think the behavior might be different enough
to get around this problem. (Also, I try to use MSI files when I can, so
they tend to be well behaved). But, the script itself works - if I run it
normally, as myself, it runs fine and I can see all of the windows as they
pop up. So, I know it's pushing all of the buttons it's supposed to, at
least when it can find them anyway.

Here is some of my code to give everyone a feeling about what I'm doing


******************************************************


function Install-Program #Calls the installer executable, calls a
redirected input function if needed, and waits until the program in done
installing
#Finally, the results of the install are then
coded into the Autoinstall registry key for this particular program
#One note, the final variable is not cast as a
string. If cast as a string, it will become an empty string, which is not
the same as $null
{

Param ([string]$InstallServerLocation, [string]$InstallFilePath,
[string]$InstallProgram, [string]$Arguments, [string]$AutoInstallVersion,
[string]$AutoInstallKey, [string]$ProgramKey, $FilePath = $null)

Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name "LastRun"
-Value (get-date -format g)

$Installer = new-object System.Diagnostics.ProcessStartInfo

$Installer.filename = ($InstallServerLocation + $InstallFilePath +
$InstallProgram)

$Installer.Arguments = $Arguments

$Installer.RedirectStandardInput = $false

$Installer.RedirectStandardOutput = $false

$Installer.RedirectStandardError = $false

$Installer.LoadUserProfile = $false

$Installer.UseShellExecute = $false

$Installer.CreateNoWindow = $false

$Installer.WindowStyle = ProcessWindowStyle.Normal

$Installerexec = [System.Diagnostics.Process]::Start($Installer)

#########################################################
#If redirected Input for a Win32 application is needed
#########################################################

compile-CSharp $WinAPIcode #Compiles the C# Code for sendmessage and
findwindow - currently commented out as it is not needed for this install

start-sleep -s 180 #Waits x seconds to
allow the executable time to get started

Start-Input #The hard coded script for sending the messages -
currently commented out as it is not needed for this install

#########################################################
#After redirected Input for a Win32 application is needed
#########################################################

$Installerexec.WaitForExit(1800000) #Makes sure the installer is done
before proceeding to the next command - this may not work with installers
that then call other programs


Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name "Exit Code"
-Value $LASTEXITCODE

if ($FilePath -ne $null) #Checks to see if $FilePath is assigned to
anything, if it is, get a version from the file provided
{
Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name
"Version" -Value (Check-FileVersion $FilePath) #getting version information
from the file provided
Write-host "Program Version from File: $FilePath"
}
else
{
Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name
"Version" -Value (Check-InstalledVersion $ProgramKey) #Otherwise, get the
version information from the Add Remove programs listing using WMI
Write-host "Program Version from WMI: $ProgramKey"
}

Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name
"AutoInstallVersion" -Value $AutoInstallVersion

}


******************************************

#########################################################
# C# Code to be compiled
#
# This uses the Win32API to find windows - Findwindow, find sub windows -
FindWindowEx, and send messages to windows - sendmessage
# The purpose of this is to provide manual keystroke input - or send
messages between windows as though it had occurred
# without having the problems of using SendKeys (Problems such as window
focus, and losing focus to another applicaton). And, finally
# having to be logged in to send these messages at all
#
# The C# code is included as a literal string - powershell doesn't
interperate this at all
#########################################################
$WinAPIcode = '
using System;
using System.Runtime.InteropServices;

namespace Win32APIStuff
{
public class CShWinAPI
{

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string
lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr
hWndChild, string lpClassName, string lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr
wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam,
IntPtr lParam);


public static IntPtr RunFindWindow(string ClassNm, string WindowNm)
{
IntPtr FindWindowVar;
FindWindowVar = FindWindow(ClassNm, WindowNm);
return FindWindowVar;
}

public static IntPtr RunFindWindowEx(IntPtr hWdParent, string
ClassNm, string WindowNm)
{
IntPtr FindWindowVar;
FindWindowVar = FindWindowEx(hWdParent, System.IntPtr.Zero,
ClassNm, WindowNm);
return FindWindowVar;
}

public static IntPtr RunSendMessage(IntPtr Window, uint Message,
IntPtr wPar, IntPtr lPar)
{
IntPtr Sent;
Sent = SendMessage(Window, Message, wPar, lPar);
return Sent;
}

public static bool RunPostMessage(IntPtr Window, uint Message,
IntPtr wPar, IntPtr lPar)
{
bool Sent;
Sent = PostMessage(Window, Message, wPar, lPar);
return Sent;
}

public static IntPtr MakeParam(int xCoordinate, int yCoordinate)
{
return (IntPtr) (((short)yCoordinate << 16) | (xCoordinate &
0xffff));
}


}


}
'
#########################################################
#End of C# Code to be compiled
#########################################################

***********************************************


This is the start of my Start-Input function so you can see how I'm sending
the messages.

******************************************

function Start-Input #This function sends the redirected input to the
particular window needed
#It can also be used to send the messages back to the
calling window
#For instance, rather than 'hitting' a key to close a
dialog box and send a message back to the calling window,
#the resulting message, can be send directly to the
calling window

{
#######
#First Screen
#######

$FoundParent = [Win32APIStuff.CShWinAPI]::RunFindWindow('#32770', 'Create
Storage Files')
write-host $FoundParent
$FoundWindow = [Win32APIStuff.CShWinAPI]::RunFindWindowEx($FoundParent,
'Button', 'Continue')
write-host $FoundWindow

[Win32APIStuff.CShWinAPI]::RunPostMessage($FoundParent, 0x111,
([Win32APIStuff.CShWinAPI]::MakeParam('1003','0')), $FoundWindow)
start-sleep -m 500

start-sleep -s 60

#######
#Second Screen
#######

$FoundParent = [Win32APIStuff.CShWinAPI]::RunFindWindow('#32770', 'Configure
Storage Area')

********************************************

Basically, I take a block of C# code and compile it, which I can then call
from powershell. The C# code allows me to access the Win32 API, so I can run
findwindow, and sendmessage. I don't think the problem is actually with the
message sending portion of the code, I just wanted everyone to be able to see
what it was doing (and sort of get it out of the way so we can worry about
where I think the real problem lies).

What I believe the real problem is, is System.Diagnostics.ProcessStartInfo.
Specifically, I'm looking for a way to allow the application to interact with
the desktop, so I can access everything else that I need. I've messed around
with a combination of LoadUserProfile, UseShellExecute, CreateNoWindow, and
WindowStyle to try to create a application that Interacts with the desktop,
but it doesn't seem to have worked. I know that I can specify a Username and
password as part of the ProcessStartInfo, but I've been trying to avoid it.
If nothing else, the scripts themselves are plain text, and I don't want to
have an administrator account's password visible. I am running this as a
specific user, but I'm doing it as part of the scheduled task. I have a
domain user defined that's a local administrator on the computers that this
script runs on.

So, that's my problem in a nutshell. Anyone have any suggestions or advice?

Thanks,

Bill V.

My System SpecsSystem Spec
Old 05-20-2008   #2 (permalink)
Jon
Guest


 

Re: Non interactive process control manipulation

It sounds a fairly elaborate approach, but I won't question that ;-)

There's a minor error at this line that I can spot

$Installer.WindowStyle = ProcessWindowStyle.Normal

which should probably be

..$Installer.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Normal

but that in itself probably wouldn't be sufficient to throw it out
completely.

It it works when you run it manually but it's not even visible as a
scheduled task, then that suggests to me that the scheduled task isn't set
up correctly. You could try scheduling a simpler script such as the
following. If you could get that to appear ok, then it may help you in
troubleshooting your main procedure.

#-----------------
$NotepadProcess = new-object System.Diagnostics.ProcessStartInfo
$NotepadProcess.filename = "notepad.exe"
$NotepadProcess.Arguments = ""
$NotepadProcess.RedirectStandardInput = $false
$NotepadProcess.RedirectStandardOutput = $false
$NotepadProcess.RedirectStandardError = $false
$NotepadProcess.LoadUserProfile = $false
$NotepadProcess.UseShellExecute = $false
$NotepadProcess.CreateNoWindow = $false
$NotepadProcess.WindowStyle =
[System.Diagnostics.ProcessWindowStyle]::Normal
$NotepadProcessexec =
[System.Diagnostics.Process]::Start($NotepadProcess)
#-----------------


--
Jon


"Bill V." <BillV@xxxxxx> wrote in message
news:E607AF17-57C5-4489-9355-A8866DB3C88D@xxxxxx
Quote:

> Hello everyone.
>
> This might be more of a .Net question, but I'm ultimately using
> powershell,
> so I thought I'd start here.
>
> Some time ago, I posted here in trying to figure out a good way of
> automating installs and other processes on the computers at my work. (I'm
> a
> PC tech at a Community College). Many educational applications aren't
> written with automation in mind, so you end up pressing a lot of buttons
> in a
> GUI to get things done. Part of my challenge was that I wanted something
> that would work whether someone was signed into the computer or not. So,
> this meant I couldn't use sendkeys, since that required someone to be
> signed
> in and have the application in focus to be able to control it (at least it
> worked this way in VBScript when I used it, and it didn't seem like things
> had changed any). Ultimately, the method I ended up using is Win32 APIs
> called through .Net (which I then was referencing through powershell)
> where I
> used Findwindow, FindwindowEX, and Sendmessage to control the applications
> that I couldn't manage any other way. I have a scheduled task that I run
> Sunday mornings (around 1:00 am) that does initial installs, and installs
> any
> updated applications since the last run.
>
> For the most part, this worked fine. Generally, I only used canned
> keystrokes when I had to, and when I did, things worked well enough. But,
> just recently, I've come across some applications that just don't want to
> work. Ultimately, I think that the problem comes down to the fact that
> since
> the apps that I'm running are scheduled tasks they don't interact with the
> desktop. The reason I've come to this conclusion is that I can run the
> script and I see the application running in the process list of the task
> manager. However, I can't find the application using Winspector Spy, and
> Findwindow doesn't find any windows of the applications. Now, I've run
> some
> other installers this way, and it's worked out, but most of the time these
> are self extracting application - so I start one executable, but I end up
> manipulating another one, so I think the behavior might be different
> enough
> to get around this problem. (Also, I try to use MSI files when I can, so
> they tend to be well behaved). But, the script itself works - if I run it
> normally, as myself, it runs fine and I can see all of the windows as they
> pop up. So, I know it's pushing all of the buttons it's supposed to, at
> least when it can find them anyway.
>
> Here is some of my code to give everyone a feeling about what I'm doing
>
>
> ******************************************************
>
>
> function Install-Program #Calls the installer executable, calls a
> redirected input function if needed, and waits until the program in done
> installing
> #Finally, the results of the install are then
> coded into the Autoinstall registry key for this particular program
> #One note, the final variable is not cast as a
> string. If cast as a string, it will become an empty string, which is not
> the same as $null
> {
>
> Param ([string]$InstallServerLocation, [string]$InstallFilePath,
> [string]$InstallProgram, [string]$Arguments, [string]$AutoInstallVersion,
> [string]$AutoInstallKey, [string]$ProgramKey, $FilePath = $null)
>
> Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name "LastRun"
> -Value (get-date -format g)
>
> $Installer = new-object System.Diagnostics.ProcessStartInfo
>
> $Installer.filename = ($InstallServerLocation + $InstallFilePath +
> $InstallProgram)
>
> $Installer.Arguments = $Arguments
>
> $Installer.RedirectStandardInput = $false
>
> $Installer.RedirectStandardOutput = $false
>
> $Installer.RedirectStandardError = $false
>
> $Installer.LoadUserProfile = $false
>
> $Installer.UseShellExecute = $false
>
> $Installer.CreateNoWindow = $false
>
> $Installer.WindowStyle = ProcessWindowStyle.Normal
>
> $Installerexec = [System.Diagnostics.Process]::Start($Installer)
>
> #########################################################
> #If redirected Input for a Win32 application is needed
> #########################################################
>
> compile-CSharp $WinAPIcode #Compiles the C# Code for sendmessage and
> findwindow - currently commented out as it is not needed for this install
>
> start-sleep -s 180 #Waits x seconds to
> allow the executable time to get started
>
> Start-Input #The hard coded script for sending the messages -
> currently commented out as it is not needed for this install
>
> #########################################################
> #After redirected Input for a Win32 application is needed
> #########################################################
>
> $Installerexec.WaitForExit(1800000) #Makes sure the installer is done
> before proceeding to the next command - this may not work with installers
> that then call other programs
>
>
> Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name "Exit Code"
> -Value $LASTEXITCODE
>
> if ($FilePath -ne $null) #Checks to see if $FilePath is assigned to
> anything, if it is, get a version from the file provided
> {
> Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name
> "Version" -Value (Check-FileVersion $FilePath) #getting version
> information
> from the file provided
> Write-host "Program Version from File: $FilePath"
> }
> else
> {
> Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name
> "Version" -Value (Check-InstalledVersion $ProgramKey) #Otherwise, get the
> version information from the Add Remove programs listing using WMI
> Write-host "Program Version from WMI: $ProgramKey"
> }
>
> Set-ItemProperty -Path ($AutoInstallKey + $ProgramKey) -Name
> "AutoInstallVersion" -Value $AutoInstallVersion
>
> }
>
>
> ******************************************
>
> #########################################################
> # C# Code to be compiled
> #
> # This uses the Win32API to find windows - Findwindow, find sub windows -
> FindWindowEx, and send messages to windows - sendmessage
> # The purpose of this is to provide manual keystroke input - or send
> messages between windows as though it had occurred
> # without having the problems of using SendKeys (Problems such as window
> focus, and losing focus to another applicaton). And, finally
> # having to be logged in to send these messages at all
> #
> # The C# code is included as a literal string - powershell doesn't
> interperate this at all
> #########################################################
> $WinAPIcode = '
> using System;
> using System.Runtime.InteropServices;
>
> namespace Win32APIStuff
> {
> public class CShWinAPI
> {
>
> [DllImport("user32.dll", SetLastError = true)]
> static extern IntPtr FindWindow(string lpClassName, string
> lpWindowName);
> [DllImport("user32.dll", SetLastError = true)]
> static extern IntPtr FindWindowEx(IntPtr hWndParent, IntPtr
> hWndChild, string lpClassName, string lpWindowName);
> [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError =
> true)]
> static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr
> wParam, IntPtr lParam);
> [DllImport("user32.dll", SetLastError = true)]
> static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr
> wParam,
> IntPtr lParam);
>
>
> public static IntPtr RunFindWindow(string ClassNm, string WindowNm)
> {
> IntPtr FindWindowVar;
> FindWindowVar = FindWindow(ClassNm, WindowNm);
> return FindWindowVar;
> }
>
> public static IntPtr RunFindWindowEx(IntPtr hWdParent, string
> ClassNm, string WindowNm)
> {
> IntPtr FindWindowVar;
> FindWindowVar = FindWindowEx(hWdParent, System.IntPtr.Zero,
> ClassNm, WindowNm);
> return FindWindowVar;
> }
>
> public static IntPtr RunSendMessage(IntPtr Window, uint Message,
> IntPtr wPar, IntPtr lPar)
> {
> IntPtr Sent;
> Sent = SendMessage(Window, Message, wPar, lPar);
> return Sent;
> }
>
> public static bool RunPostMessage(IntPtr Window, uint Message,
> IntPtr wPar, IntPtr lPar)
> {
> bool Sent;
> Sent = PostMessage(Window, Message, wPar, lPar);
> return Sent;
> }
>
> public static IntPtr MakeParam(int xCoordinate, int yCoordinate)
> {
> return (IntPtr) (((short)yCoordinate << 16) | (xCoordinate &
> 0xffff));
> }
>
>
> }
>
>
> }
> '
> #########################################################
> #End of C# Code to be compiled
> #########################################################
>
> ***********************************************
>
>
> This is the start of my Start-Input function so you can see how I'm
> sending
> the messages.
>
> ******************************************
>
> function Start-Input #This function sends the redirected input to the
> particular window needed
> #It can also be used to send the messages back to the
> calling window
> #For instance, rather than 'hitting' a key to close a
> dialog box and send a message back to the calling window,
> #the resulting message, can be send directly to the
> calling window
>
> {
> #######
> #First Screen
> #######
>
> $FoundParent = [Win32APIStuff.CShWinAPI]::RunFindWindow('#32770', 'Create
> Storage Files')
> write-host $FoundParent
> $FoundWindow = [Win32APIStuff.CShWinAPI]::RunFindWindowEx($FoundParent,
> 'Button', 'Continue')
> write-host $FoundWindow
>
> [Win32APIStuff.CShWinAPI]::RunPostMessage($FoundParent, 0x111,
> ([Win32APIStuff.CShWinAPI]::MakeParam('1003','0')), $FoundWindow)
> start-sleep -m 500
>
> start-sleep -s 60
>
> #######
> #Second Screen
> #######
>
> $FoundParent = [Win32APIStuff.CShWinAPI]::RunFindWindow('#32770',
> 'Configure
> Storage Area')
>
> ********************************************
>
> Basically, I take a block of C# code and compile it, which I can then call
> from powershell. The C# code allows me to access the Win32 API, so I can
> run
> findwindow, and sendmessage. I don't think the problem is actually with
> the
> message sending portion of the code, I just wanted everyone to be able to
> see
> what it was doing (and sort of get it out of the way so we can worry about
> where I think the real problem lies).
>
> What I believe the real problem is, is
> System.Diagnostics.ProcessStartInfo.
> Specifically, I'm looking for a way to allow the application to interact
> with
> the desktop, so I can access everything else that I need. I've messed
> around
> with a combination of LoadUserProfile, UseShellExecute, CreateNoWindow,
> and
> WindowStyle to try to create a application that Interacts with the
> desktop,
> but it doesn't seem to have worked. I know that I can specify a Username
> and
> password as part of the ProcessStartInfo, but I've been trying to avoid
> it.
> If nothing else, the scripts themselves are plain text, and I don't want
> to
> have an administrator account's password visible. I am running this as a
> specific user, but I'm doing it as part of the scheduled task. I have a
> domain user defined that's a local administrator on the computers that
> this
> script runs on.
>
> So, that's my problem in a nutshell. Anyone have any suggestions or
> advice?
>
> Thanks,
>
> Bill V.
My System SpecsSystem Spec
Old 05-20-2008   #3 (permalink)
Bill V.
Guest


 

Re: Non interactive process control manipulation

Oops, I should elaborate a bit. It does start the program. When I go into
the task manager, I can see the executable running. But, using Winspector
Spy (I didn't have a copy of Spy ++) I can't find any of it's windows. Also,
the findwindow function returns a 0, meaning it failed to find the window as
well.

Don't worry, I'd definitely say it's overly elaborate as well. I'm sure
that it could be cleaned up quite a bit, and that there's things that could
be done better. Sadly, "faking it" seems to be a fairly big part of
scripting, and I hadn't found anyone else who was doing quite the same thing.
But, I wanted a way to keep the computers here up to date, and to do so I
needed an automated way of going about things (otherwise it never happens
until theres a massive update and computers are reimaged. But then, the same
thing starts happening and the computer start getting out of date again...).
Also, though it's hard to tell from this snippit of code, I tried to write
things so it was fairly easy to update for new programs. Often, I can just
update a few variables at the begining of the code, and update a switch
statement at the end of it, and I have something that works for a whole new
piece of software (I've been able to manage perhaps 20 + programs this way,
not counting the regular updates to plugins that occur regularly).
Previously, I had done some minor things with VBScript, but powershell can do
things in a much more concise manner, it's a shame to go back (and
redirecting input doesn't work the way I want it to).

I'll check out the code you provided and see how it goes, but I don't think
it's a so much a matter of exactly how I'm starting the process (since I've
successfully gotten several of them to work so far), but that this particular
process seems to behave differently than the others I've dealt with.

I've been looking into using CreateProcess from the Win API, but it seems a
bit messy - I hate that I can't stick to .Net and powershell as it is.

Thanks for your help!

-Bill V.
"Jon" wrote:
Quote:

> It sounds a fairly elaborate approach, but I won't question that ;-)
>
> There's a minor error at this line that I can spot
>
> $Installer.WindowStyle = ProcessWindowStyle.Normal
>
> which should probably be
>
> ..$Installer.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Normal
>
> but that in itself probably wouldn't be sufficient to throw it out
> completely.
>
> It it works when you run it manually but it's not even visible as a
> scheduled task, then that suggests to me that the scheduled task isn't set
> up correctly. You could try scheduling a simpler script such as the
> following. If you could get that to appear ok, then it may help you in
> troubleshooting your main procedure.
My System SpecsSystem Spec
Old 05-24-2008   #4 (permalink)
Alex K. Angelopoulos
Guest


 

Re: Non interactive process control manipulation

Quick remark on a side comment you made - you may find it useful, even
though it doesn’t deal with the current problem you're trying to handle.

"Bill V." <BillV@xxxxxx> wrote in message
news:6EED50E2-7697-44EE-8576-F699763C3BFD@xxxxxx
Quote:

> Previously, I had done some minor things with VBScript ...
> ... (and
> redirecting input doesn't work the way I want it to).
I may be able to shed some light on that - I use PowerShell and WSH together
quite a bit, and the stdin problem does have a solution. I'm assuming you
see the input pipeline break when you run a WSH script within a 32-bit
cmd.exe pipeline, kind of like this
<somecommand> | somescript.vbs
This breaks input, even if CScript is set as the default WSH host.

The problem is that the shell API used for process creation initially
assumes it is dealing with an executable, and when the process creation
fails, the shell then tries to find a document handler for somescript.vbs
and launches that application with the script name and the script's
arguments as the handler's arguments - but it never hooks up the input
pipeline. The same thing happens to Perl scripts, for example, which is why
there are batch file wrappers for console Perl scripts in Windows Perl
distributions.

If you _are_ occasionally using WSH scripts for things, you can work around
this in various ways, depending on what you have available.

+ If you use WSH scripts from within PowerShell, they do get stdin properly
handled when cscript is the default host - this is one of the helper
features built in to PowerShell for other script languages.

+ The 64-bit version of cmd.exe also fixes this problem, it appears; if
cscript is the default host, WSH scripts don't get broken input streams.

+ You can explicitly specify cscript on the command line; this works, but it
can be awkward because you need to specify the path to the script even if it
is in your search path.

+ The low-maintenance way is to do what Perl does: create a wrapper script
for the WSH script. What I do is simply create a .cmd file with the same
base name as a WSH script, in the same folder, containing the following
single line:
@cscript //Nologo %~dpn0.vbs %*
In this case, I can just specify the name "somescript" and somescript.cmd
gets found by command search before somescript.vbs; it then performs the
explicit script launch with cscript no matter what the default script host
is.


My System SpecsSystem Spec
Closed Thread

Thread Tools
Display Modes



Similar Threads
Thread Thread Starter Forum Replies Last Post
Start an interactive process under Local Syste Ondrej Sevecek Vista security 1 04-21-2008 12:36 PM
Interactive powershell host or start a new process ghandi PowerShell 11 03-24-2008 11:07 PM
Interactive logon process initialization has failed. RCC Vista account administration 1 03-05-2008 04:16 AM
Interactive Logon Process failed. (Windows Vista) CJL Vista performance & maintenance 1 10-11-2007 12:51 AM
interactive logon process initialization has failed wyocowboy Vista General 4 05-07-2007 04:09 PM


Update your Vista Drivers Update Your Drivers Now!!

Vistax64.com is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media 2005-2008