Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > PowerShell

Vista - Win32 API's in Powershell - FindWindow and SendMessage

Reply
 
Old 11-28-2007   #1 (permalink)
Bill V.


 
 

Win32 API's in Powershell - FindWindow and SendMessage

Hello everyone.

I'm fairly new to Powershell (as is nearly everyone, I imagine) and I'm just
starting to get my feet wet. And, what better way to learn a new language
than to attempt to tackle an insanely complicated process!

I'm a PC Tech at a college who is trying to make my life easier by
automating software installs (rather than keeping several ghost images for
each computer type, my ultimate goal is to keep clean images of basic
computer models, and use automation to install the software required on the
computers. I also want to schedule the script to perform regular updates as
well, but that's some ways off yet - I'd be happy with it running through
once). Quite a bit of the educational software out there is, to be blunt,
poorly written - at least regarding their installers. Typically, there are
no command line options for installed software, just keystrokes and mouse
clicks in the gui provided. I'm trying to automate this, without using
sendkeys - Ideally the script should be able to run whether someone is logged
on or not - an option I don't have with sendkeys. (Not to mention the basic
problems of applications loosing focus even if someone is logged in.)

However, all is not lost - it looks like FindWindow and SendMessage could be
the answer to my prayers, if I could only get them to work. (from what I
gather, I can send messages to the window, even if no one is currently logged
on - exactly what I'm looking for) Actually, I have FindWindow working, but I
can't get SendMessage to run properly. Right now, I can find the window I'm
looking for (Window type '#32770' - an Install Shield window, with a name
of"Welcome"). All, I'm trying to do currently is hit Alt+N to move on to the
next window. Once I get that working, it should be downhill from there. The
code will likely look familiar to people out there - it's been the result of
my searching the Internet for just how to do this.

I'll follow with my code and error message below.
#####
Code
#####

$domain = [AppDomain]::CurrentDomain

$name = New-Object Reflection.AssemblyName 'PInvokeFindWindowAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$FindWindowmodule = $assembly.DefineDynamicModule('PInvokeFindWindowModule')
$FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
[Type[]]$FindWindowparameterTypes = [string], [string]
$FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
$Constructor =
[Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$FindWindowattr = New-Object Reflection.Emit.CustomAttributeBuilder
$Constructor, 'user32'
$FindWindowmethod.SetCustomAttribute($FindWindowattr)
$realFindWindowType = $FindWindowtype.CreateType()

[object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"


[IntPtr]$FoundWindow = $realFindWindowType.InvokeMember('FindWindow',
'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)


$name = New-Object Reflection.AssemblyName 'PInvokeSendMessageAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$SendMessagemodule = $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
$SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
[Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32], [Int32]
$SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
$Constructor =
[Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
$Constructor, 'user32'
$SendMessagemethod.SetCustomAttribute($SendMessageattr)
$realSendMessageType = $SendMessagetype.CreateType()







[object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
[Int32]0x00000012, [Int32]0x20380001

$realSendMessageType.InvokeMember('SendMessage',
'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)

[object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
[Int32]0x00000009, [Int32]0xa00f0001

$realSendMessageType.InvokeMember('SendMessage',
'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)


#####
Errors
#####
PS F:\PowerShell Scripts\Automated Installs - Install Pearson CourseCompass>
..\
endMessage.ps1
Exception calling "InvokeMember" with "5" argument(s): "Method
'PInvokeSendMess
ageType.SendMessage' not found."
At F:\PowerShell Scripts\Automated Installs - Install Pearson
CourseCompass\Sen
dMessage.ps1:38 char:34
+ $realSendMessageType.InvokeMember( <<<< 'SendMessage',
'Public,Static,InvokeM
ethod', $null, $null, $SendMessageargs)
Exception calling "InvokeMember" with "5" argument(s): "Method
'PInvokeSendMess
ageType.SendMessage' not found."
At F:\PowerShell Scripts\Automated Installs - Install Pearson
CourseCompass\Sen
dMessage.ps1:42 char:34
+ $realSendMessageType.InvokeMember( <<<< 'SendMessage',
'Public,Static,InvokeM
ethod', $null, $null, $SendMessageargs)


#####
Parting Message
#####

I'm more of a scripter than a programmer (I can't claim to know .Net by any
means) so I'm hoping the answer is failry obvious. Hopefully a second pair
of eyes is all it will take.

Thanks!

Bill

My System SpecsSystem Spec
Old 11-28-2007   #2 (permalink)
Shay Levi


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

IMO, AutoIt is your friend. Writing this kind of automations in PowerShell
can be quiet a challenge.
Few days ago I blogged on a new set of Cmdlets, byDr. James McCaffrey, designed
to perform Windows UI automation tasks
http://msdn.microsoft.com/msdnmag/is...n/default.aspx

Anyway, for now, AutoIt can perform a wide range of GUI automations, and
based on my own expreince, its the
best GUI automation tool I've know. You can get more info on http://www.autoitscript.com/autoit3.


-----
Shay Levi
$cript Fanatic
http://scriptolog.blogspot.com
Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic


Quote:

> Hello everyone.
>
> I'm fairly new to Powershell (as is nearly everyone, I imagine) and
> I'm just starting to get my feet wet. And, what better way to learn a
> new language than to attempt to tackle an insanely complicated
> process!
>
> I'm a PC Tech at a college who is trying to make my life easier by
> automating software installs (rather than keeping several ghost images
> for each computer type, my ultimate goal is to keep clean images of
> basic computer models, and use automation to install the software
> required on the computers. I also want to schedule the script to
> perform regular updates as well, but that's some ways off yet - I'd be
> happy with it running through once). Quite a bit of the educational
> software out there is, to be blunt, poorly written - at least
> regarding their installers. Typically, there are no command line
> options for installed software, just keystrokes and mouse clicks in
> the gui provided. I'm trying to automate this, without using sendkeys
> - Ideally the script should be able to run whether someone is logged
> on or not - an option I don't have with sendkeys. (Not to mention the
> basic problems of applications loosing focus even if someone is logged
> in.)
>
> However, all is not lost - it looks like FindWindow and SendMessage
> could be the answer to my prayers, if I could only get them to work.
> (from what I gather, I can send messages to the window, even if no
> one is currently logged on - exactly what I'm looking for) Actually, I
> have FindWindow working, but I can't get SendMessage to run properly.
> Right now, I can find the window I'm looking for (Window type '#32770'
> - an Install Shield window, with a name of"Welcome"). All, I'm trying
> to do currently is hit Alt+N to move on to the next window. Once I
> get that working, it should be downhill from there. The code will
> likely look familiar to people out there - it's been the result of my
> searching the Internet for just how to do this.
>
> I'll follow with my code and error message below.
> #####
> Code
> #####
> $domain = [AppDomain]::CurrentDomain
>
> $name = New-Object Reflection.AssemblyName 'PInvokeFindWindowAssembly'
> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> $FindWindowmodule =
> $assembly.DefineDynamicModule('PInvokeFindWindowModule')
> $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
> [Type[]]$FindWindowparameterTypes = [string], [string]
> $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
> 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
> $Constructor =
> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> $FindWindowattr = New-Object Reflection.Emit.CustomAttributeBuilder
> $Constructor, 'user32'
> $FindWindowmethod.SetCustomAttribute($FindWindowattr)
> $realFindWindowType = $FindWindowtype.CreateType()
> [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
>
> [IntPtr]$FoundWindow = $realFindWindowType.InvokeMember('FindWindow',
> 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
>
> $name = New-Object Reflection.AssemblyName
> 'PInvokeSendMessageAssembly'
> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> $SendMessagemodule =
> $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
> $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
> [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32],
> [Int32]
> $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
> 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
> $Constructor =
> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> $SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
> $Constructor, 'user32'
> $SendMessagemethod.SetCustomAttribute($SendMessageattr)
> $realSendMessageType = $SendMessagetype.CreateType()
> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
> [Int32]0x00000012, [Int32]0x20380001
>
> $realSendMessageType.InvokeMember('SendMessage',
> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>
> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
> [Int32]0x00000009, [Int32]0xa00f0001
>
> $realSendMessageType.InvokeMember('SendMessage',
> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>
> #####
> Errors
> #####
> PS F:\PowerShell Scripts\Automated Installs - Install Pearson
> CourseCompass>
> .\
> endMessage.ps1
> Exception calling "InvokeMember" with "5" argument(s): "Method
> 'PInvokeSendMess
> ageType.SendMessage' not found."
> At F:\PowerShell Scripts\Automated Installs - Install Pearson
> CourseCompass\Sen
> dMessage.ps1:38 char:34
> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> 'Public,Static,InvokeM
> ethod', $null, $null, $SendMessageargs)
> Exception calling "InvokeMember" with "5" argument(s): "Method
> 'PInvokeSendMess
> ageType.SendMessage' not found."
> At F:\PowerShell Scripts\Automated Installs - Install Pearson
> CourseCompass\Sen
> dMessage.ps1:42 char:34
> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> 'Public,Static,InvokeM
> ethod', $null, $null, $SendMessageargs)
> #####
> Parting Message
> #####
> I'm more of a scripter than a programmer (I can't claim to know .Net
> by any means) so I'm hoping the answer is failry obvious. Hopefully a
> second pair of eyes is all it will take.
>
> Thanks!
>
> Bill
>

My System SpecsSystem Spec
Old 11-28-2007   #3 (permalink)
ebgreen


 
 

RE: Win32 API's in Powershell - FindWindow and SendMessage

I would suggest reading this article in the latest issue of MSDN magazine:
http://msdn.microsoft.com/msdnmag/issues/07/12/TestRun/

"Bill V." wrote:
Quote:

> Hello everyone.
>
> I'm fairly new to Powershell (as is nearly everyone, I imagine) and I'm just
> starting to get my feet wet. And, what better way to learn a new language
> than to attempt to tackle an insanely complicated process!
>
> I'm a PC Tech at a college who is trying to make my life easier by
> automating software installs (rather than keeping several ghost images for
> each computer type, my ultimate goal is to keep clean images of basic
> computer models, and use automation to install the software required on the
> computers. I also want to schedule the script to perform regular updates as
> well, but that's some ways off yet - I'd be happy with it running through
> once). Quite a bit of the educational software out there is, to be blunt,
> poorly written - at least regarding their installers. Typically, there are
> no command line options for installed software, just keystrokes and mouse
> clicks in the gui provided. I'm trying to automate this, without using
> sendkeys - Ideally the script should be able to run whether someone is logged
> on or not - an option I don't have with sendkeys. (Not to mention the basic
> problems of applications loosing focus even if someone is logged in.)
>
> However, all is not lost - it looks like FindWindow and SendMessage could be
> the answer to my prayers, if I could only get them to work. (from what I
> gather, I can send messages to the window, even if no one is currently logged
> on - exactly what I'm looking for) Actually, I have FindWindow working, but I
> can't get SendMessage to run properly. Right now, I can find the window I'm
> looking for (Window type '#32770' - an Install Shield window, with a name
> of"Welcome"). All, I'm trying to do currently is hit Alt+N to move on to the
> next window. Once I get that working, it should be downhill from there. The
> code will likely look familiar to people out there - it's been the result of
> my searching the Internet for just how to do this.
>
> I'll follow with my code and error message below.
> #####
> Code
> #####
>
> $domain = [AppDomain]::CurrentDomain
>
> $name = New-Object Reflection.AssemblyName 'PInvokeFindWindowAssembly'
> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> $FindWindowmodule = $assembly.DefineDynamicModule('PInvokeFindWindowModule')
> $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
> [Type[]]$FindWindowparameterTypes = [string], [string]
> $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
> 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
> $Constructor =
> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> $FindWindowattr = New-Object Reflection.Emit.CustomAttributeBuilder
> $Constructor, 'user32'
> $FindWindowmethod.SetCustomAttribute($FindWindowattr)
> $realFindWindowType = $FindWindowtype.CreateType()
>
> [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
>
>
> [IntPtr]$FoundWindow = $realFindWindowType.InvokeMember('FindWindow',
> 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
>
>
> $name = New-Object Reflection.AssemblyName 'PInvokeSendMessageAssembly'
> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> $SendMessagemodule = $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
> $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
> [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32], [Int32]
> $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
> 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
> $Constructor =
> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> $SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
> $Constructor, 'user32'
> $SendMessagemethod.SetCustomAttribute($SendMessageattr)
> $realSendMessageType = $SendMessagetype.CreateType()
>
>
>
>
>
>
>
> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
> [Int32]0x00000012, [Int32]0x20380001
>
> $realSendMessageType.InvokeMember('SendMessage',
> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>
> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
> [Int32]0x00000009, [Int32]0xa00f0001
>
> $realSendMessageType.InvokeMember('SendMessage',
> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>
>
> #####
> Errors
> #####
> PS F:\PowerShell Scripts\Automated Installs - Install Pearson CourseCompass>
> .\
> endMessage.ps1
> Exception calling "InvokeMember" with "5" argument(s): "Method
> 'PInvokeSendMess
> ageType.SendMessage' not found."
> At F:\PowerShell Scripts\Automated Installs - Install Pearson
> CourseCompass\Sen
> dMessage.ps1:38 char:34
> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> 'Public,Static,InvokeM
> ethod', $null, $null, $SendMessageargs)
> Exception calling "InvokeMember" with "5" argument(s): "Method
> 'PInvokeSendMess
> ageType.SendMessage' not found."
> At F:\PowerShell Scripts\Automated Installs - Install Pearson
> CourseCompass\Sen
> dMessage.ps1:42 char:34
> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> 'Public,Static,InvokeM
> ethod', $null, $null, $SendMessageargs)
>
>
> #####
> Parting Message
> #####
>
> I'm more of a scripter than a programmer (I can't claim to know .Net by any
> means) so I'm hoping the answer is failry obvious. Hopefully a second pair
> of eyes is all it will take.
>
> Thanks!
>
> Bill
My System SpecsSystem Spec
Old 11-28-2007   #4 (permalink)
Bill V.


 
 

RE: Win32 API's in Powershell - FindWindow and SendMessage

I'll have to look into System.Management.Automation.dll and see if it has
what I need. Have you used it any? Can it send keystrokes even to out of
focus windows?

Thanks!

-Bill
"ebgreen" wrote:
Quote:

> I would suggest reading this article in the latest issue of MSDN magazine:
> http://msdn.microsoft.com/msdnmag/issues/07/12/TestRun/
>
> "Bill V." wrote:
>
Quote:

> > Hello everyone.
> >
> > I'm fairly new to Powershell (as is nearly everyone, I imagine) and I'm just
> > starting to get my feet wet. And, what better way to learn a new language
> > than to attempt to tackle an insanely complicated process!
> >
> > I'm a PC Tech at a college who is trying to make my life easier by
> > automating software installs (rather than keeping several ghost images for
> > each computer type, my ultimate goal is to keep clean images of basic
> > computer models, and use automation to install the software required on the
> > computers. I also want to schedule the script to perform regular updates as
> > well, but that's some ways off yet - I'd be happy with it running through
> > once). Quite a bit of the educational software out there is, to be blunt,
> > poorly written - at least regarding their installers. Typically, there are
> > no command line options for installed software, just keystrokes and mouse
> > clicks in the gui provided. I'm trying to automate this, without using
> > sendkeys - Ideally the script should be able to run whether someone is logged
> > on or not - an option I don't have with sendkeys. (Not to mention the basic
> > problems of applications loosing focus even if someone is logged in.)
> >
> > However, all is not lost - it looks like FindWindow and SendMessage could be
> > the answer to my prayers, if I could only get them to work. (from what I
> > gather, I can send messages to the window, even if no one is currently logged
> > on - exactly what I'm looking for) Actually, I have FindWindow working, but I
> > can't get SendMessage to run properly. Right now, I can find the window I'm
> > looking for (Window type '#32770' - an Install Shield window, with a name
> > of"Welcome"). All, I'm trying to do currently is hit Alt+N to move on to the
> > next window. Once I get that working, it should be downhill from there. The
> > code will likely look familiar to people out there - it's been the result of
> > my searching the Internet for just how to do this.
> >
> > I'll follow with my code and error message below.
> > #####
> > Code
> > #####
> >
> > $domain = [AppDomain]::CurrentDomain
> >
> > $name = New-Object Reflection.AssemblyName 'PInvokeFindWindowAssembly'
> > $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> > $FindWindowmodule = $assembly.DefineDynamicModule('PInvokeFindWindowModule')
> > $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
> > [Type[]]$FindWindowparameterTypes = [string], [string]
> > $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
> > 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
> > $Constructor =
> > [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> > $FindWindowattr = New-Object Reflection.Emit.CustomAttributeBuilder
> > $Constructor, 'user32'
> > $FindWindowmethod.SetCustomAttribute($FindWindowattr)
> > $realFindWindowType = $FindWindowtype.CreateType()
> >
> > [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
> >
> >
> > [IntPtr]$FoundWindow = $realFindWindowType.InvokeMember('FindWindow',
> > 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
> >
> >
> > $name = New-Object Reflection.AssemblyName 'PInvokeSendMessageAssembly'
> > $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> > $SendMessagemodule = $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
> > $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
> > [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32], [Int32]
> > $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
> > 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
> > $Constructor =
> > [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> > $SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
> > $Constructor, 'user32'
> > $SendMessagemethod.SetCustomAttribute($SendMessageattr)
> > $realSendMessageType = $SendMessagetype.CreateType()
> >
> >
> >
> >
> >
> >
> >
> > [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
> > [Int32]0x00000012, [Int32]0x20380001
> >
> > $realSendMessageType.InvokeMember('SendMessage',
> > 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
> >
> > [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
> > [Int32]0x00000009, [Int32]0xa00f0001
> >
> > $realSendMessageType.InvokeMember('SendMessage',
> > 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
> >
> >
> > #####
> > Errors
> > #####
> > PS F:\PowerShell Scripts\Automated Installs - Install Pearson CourseCompass>
> > .\
> > endMessage.ps1
> > Exception calling "InvokeMember" with "5" argument(s): "Method
> > 'PInvokeSendMess
> > ageType.SendMessage' not found."
> > At F:\PowerShell Scripts\Automated Installs - Install Pearson
> > CourseCompass\Sen
> > dMessage.ps1:38 char:34
> > + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> > 'Public,Static,InvokeM
> > ethod', $null, $null, $SendMessageargs)
> > Exception calling "InvokeMember" with "5" argument(s): "Method
> > 'PInvokeSendMess
> > ageType.SendMessage' not found."
> > At F:\PowerShell Scripts\Automated Installs - Install Pearson
> > CourseCompass\Sen
> > dMessage.ps1:42 char:34
> > + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> > 'Public,Static,InvokeM
> > ethod', $null, $null, $SendMessageargs)
> >
> >
> > #####
> > Parting Message
> > #####
> >
> > I'm more of a scripter than a programmer (I can't claim to know .Net by any
> > means) so I'm hoping the answer is failry obvious. Hopefully a second pair
> > of eyes is all it will take.
> >
> > Thanks!
> >
> > Bill
My System SpecsSystem Spec
Old 11-28-2007   #5 (permalink)
Bill V.


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

You're the second person to mention that article (in nearly as many minutes).
I'm planning on looking the cmd-lets over (when I get home) and I'll see if
it helps me any. It certainly would be a cleaner way to get things working.

Ironically, I checked out AutoIt earlier this month (I've been working on
this problem off an on for a while - I've just finally gotten the chance to
pick it back up again). It looked like it suffered from the same problem I
had with sendkeys - you had to be logged in for things to function properly.
I asked around in the genral forum if it could send messages to out of focus
apps, but I never got a response (and i got back to work and hadn't gotten
back to things since then).


Thanks
-Bill

"Shay Levi" wrote:
Quote:

> IMO, AutoIt is your friend. Writing this kind of automations in PowerShell
> can be quiet a challenge.
> Few days ago I blogged on a new set of Cmdlets, byDr. James McCaffrey, designed
> to perform Windows UI automation tasks
> http://msdn.microsoft.com/msdnmag/is...n/default.aspx
>
> Anyway, for now, AutoIt can perform a wide range of GUI automations, and
> based on my own expreince, its the
> best GUI automation tool I've know. You can get more info on http://www.autoitscript.com/autoit3.
>
>
> -----
> Shay Levi
> $cript Fanatic
> http://scriptolog.blogspot.com
> Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic
>
>
>
Quote:

> > Hello everyone.
> >
> > I'm fairly new to Powershell (as is nearly everyone, I imagine) and
> > I'm just starting to get my feet wet. And, what better way to learn a
> > new language than to attempt to tackle an insanely complicated
> > process!
> >
> > I'm a PC Tech at a college who is trying to make my life easier by
> > automating software installs (rather than keeping several ghost images
> > for each computer type, my ultimate goal is to keep clean images of
> > basic computer models, and use automation to install the software
> > required on the computers. I also want to schedule the script to
> > perform regular updates as well, but that's some ways off yet - I'd be
> > happy with it running through once). Quite a bit of the educational
> > software out there is, to be blunt, poorly written - at least
> > regarding their installers. Typically, there are no command line
> > options for installed software, just keystrokes and mouse clicks in
> > the gui provided. I'm trying to automate this, without using sendkeys
> > - Ideally the script should be able to run whether someone is logged
> > on or not - an option I don't have with sendkeys. (Not to mention the
> > basic problems of applications loosing focus even if someone is logged
> > in.)
> >
> > However, all is not lost - it looks like FindWindow and SendMessage
> > could be the answer to my prayers, if I could only get them to work.
> > (from what I gather, I can send messages to the window, even if no
> > one is currently logged on - exactly what I'm looking for) Actually, I
> > have FindWindow working, but I can't get SendMessage to run properly.
> > Right now, I can find the window I'm looking for (Window type '#32770'
> > - an Install Shield window, with a name of"Welcome"). All, I'm trying
> > to do currently is hit Alt+N to move on to the next window. Once I
> > get that working, it should be downhill from there. The code will
> > likely look familiar to people out there - it's been the result of my
> > searching the Internet for just how to do this.
> >
> > I'll follow with my code and error message below.
> > #####
> > Code
> > #####
> > $domain = [AppDomain]::CurrentDomain
> >
> > $name = New-Object Reflection.AssemblyName 'PInvokeFindWindowAssembly'
> > $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> > $FindWindowmodule =
> > $assembly.DefineDynamicModule('PInvokeFindWindowModule')
> > $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
> > [Type[]]$FindWindowparameterTypes = [string], [string]
> > $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
> > 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
> > $Constructor =
> > [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> > $FindWindowattr = New-Object Reflection.Emit.CustomAttributeBuilder
> > $Constructor, 'user32'
> > $FindWindowmethod.SetCustomAttribute($FindWindowattr)
> > $realFindWindowType = $FindWindowtype.CreateType()
> > [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
> >
> > [IntPtr]$FoundWindow = $realFindWindowType.InvokeMember('FindWindow',
> > 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
> >
> > $name = New-Object Reflection.AssemblyName
> > 'PInvokeSendMessageAssembly'
> > $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> > $SendMessagemodule =
> > $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
> > $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
> > [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32],
> > [Int32]
> > $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
> > 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
> > $Constructor =
> > [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
> > $SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
> > $Constructor, 'user32'
> > $SendMessagemethod.SetCustomAttribute($SendMessageattr)
> > $realSendMessageType = $SendMessagetype.CreateType()
> > [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
> > [Int32]0x00000012, [Int32]0x20380001
> >
> > $realSendMessageType.InvokeMember('SendMessage',
> > 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
> >
> > [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
> > [Int32]0x00000009, [Int32]0xa00f0001
> >
> > $realSendMessageType.InvokeMember('SendMessage',
> > 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
> >
> > #####
> > Errors
> > #####
> > PS F:\PowerShell Scripts\Automated Installs - Install Pearson
> > CourseCompass>
> > .\
> > endMessage.ps1
> > Exception calling "InvokeMember" with "5" argument(s): "Method
> > 'PInvokeSendMess
> > ageType.SendMessage' not found."
> > At F:\PowerShell Scripts\Automated Installs - Install Pearson
> > CourseCompass\Sen
> > dMessage.ps1:38 char:34
> > + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> > 'Public,Static,InvokeM
> > ethod', $null, $null, $SendMessageargs)
> > Exception calling "InvokeMember" with "5" argument(s): "Method
> > 'PInvokeSendMess
> > ageType.SendMessage' not found."
> > At F:\PowerShell Scripts\Automated Installs - Install Pearson
> > CourseCompass\Sen
> > dMessage.ps1:42 char:34
> > + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> > 'Public,Static,InvokeM
> > ethod', $null, $null, $SendMessageargs)
> > #####
> > Parting Message
> > #####
> > I'm more of a scripter than a programmer (I can't claim to know .Net
> > by any means) so I'm hoping the answer is failry obvious. Hopefully a
> > second pair of eyes is all it will take.
> >
> > Thanks!
> >
> > Bill
> >
>
>
>
My System SpecsSystem Spec
Old 11-28-2007   #6 (permalink)
Marco Shaw [MVP]


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

Bill V. wrote:
Quote:

> I'll have to look into System.Management.Automation.dll and see if it has
> what I need. Have you used it any? Can it send keystrokes even to out of
> focus windows?
As far as I know, you won't be able to use that DLL to any keystroke
automation.

Marco
My System SpecsSystem Spec
Old 11-28-2007   #7 (permalink)
Marco Shaw [MVP]


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

Quote:

> Ironically, I checked out AutoIt earlier this month (I've been working on
> this problem off an on for a while - I've just finally gotten the chance to
> pick it back up again). It looked like it suffered from the same problem I
> had with sendkeys - you had to be logged in for things to function properly.
> I asked around in the genral forum if it could send messages to out of focus
> apps, but I never got a response (and i got back to work and hadn't gotten
> back to things since then).
I don't see a way that AutoItX can send keys to an out-of-focus window,
but can't you just bring that window into focus first before sending
keystrokes to it?

"WinActivate
------------------------
Activates (gives focus to) a window.

WinActivate "title" [, "text"]

Parameters
title The title of the window to activate.
text [optional] The text of the window to activate. "

Marco


--
Microsoft MVP - Windows PowerShell
http://www.microsoft.com/mvp

PowerGadgets MVP
http://www.powergadgets.com/mvp

Blog:
http://marcoshaw.blogspot.com
My System SpecsSystem Spec
Old 11-29-2007   #8 (permalink)
Shay Levi


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

From my exprience, clicking on unfocused window control shouldn't be a problem,
use the ControlClick function

ControlClick ( "title", "text", controlID [, button] [, clicks]] )


Here's a test:

Open a few explorer windows, then execute this in AutoIt:

Run("control desk.cpl")
WinWait("Display Properties")
Sleep(3000)
; now manually, click another window to make it the active window
ControlClick ( "Display Properties", "", "Button1")
; you should see the "Save As" dialog


HTH

-----
Shay Levi
$cript Fanatic
http://scriptolog.blogspot.com
Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic


Quote:

> You're the second person to mention that article (in nearly as many
> minutes).
> I'm planning on looking the cmd-lets over (when I get home) and I'll
> see if
> it helps me any. It certainly would be a cleaner way to get things
> working.
> Ironically, I checked out AutoIt earlier this month (I've been working
> on this problem off an on for a while - I've just finally gotten the
> chance to pick it back up again). It looked like it suffered from the
> same problem I had with sendkeys - you had to be logged in for things
> to function properly. I asked around in the genral forum if it could
> send messages to out of focus apps, but I never got a response (and i
> got back to work and hadn't gotten back to things since then).
>
> Thanks
> -Bill
> "Shay Levi" wrote:
>
Quote:

>> IMO, AutoIt is your friend. Writing this kind of automations in
>> PowerShell
>> can be quiet a challenge.
>> Few days ago I blogged on a new set of Cmdlets, byDr. James
>> McCaffrey, designed
>> to perform Windows UI automation tasks
>> http://msdn.microsoft.com/msdnmag/is...n/default.aspx
>> Anyway, for now, AutoIt can perform a wide range of GUI automations,
>> and
>> based on my own expreince, its the
>> best GUI automation tool I've know. You can get more info on
>> http://www.autoitscript.com/autoit3.
>> -----
>> Shay Levi
>> $cript Fanatic
>> http://scriptolog.blogspot.com
>> Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic
Quote:

>>> Hello everyone.
>>>
>>> I'm fairly new to Powershell (as is nearly everyone, I imagine) and
>>> I'm just starting to get my feet wet. And, what better way to learn
>>> a new language than to attempt to tackle an insanely complicated
>>> process!
>>>
>>> I'm a PC Tech at a college who is trying to make my life easier by
>>> automating software installs (rather than keeping several ghost
>>> images for each computer type, my ultimate goal is to keep clean
>>> images of basic computer models, and use automation to install the
>>> software required on the computers. I also want to schedule the
>>> script to perform regular updates as well, but that's some ways off
>>> yet - I'd be happy with it running through once). Quite a bit of
>>> the educational software out there is, to be blunt, poorly written -
>>> at least regarding their installers. Typically, there are no
>>> command line options for installed software, just keystrokes and
>>> mouse clicks in the gui provided. I'm trying to automate this,
>>> without using sendkeys - Ideally the script should be able to run
>>> whether someone is logged on or not - an option I don't have with
>>> sendkeys. (Not to mention the basic problems of applications
>>> loosing focus even if someone is logged in.)
>>>
>>> However, all is not lost - it looks like FindWindow and SendMessage
>>> could be the answer to my prayers, if I could only get them to work.
>>> (from what I gather, I can send messages to the window, even if
>>> no one is currently logged on - exactly what I'm looking for)
>>> Actually, I have FindWindow working, but I can't get SendMessage to
>>> run properly. Right now, I can find the window I'm looking for
>>> (Window type '#32770' - an Install Shield window, with a name
>>> of"Welcome"). All, I'm trying to do currently is hit Alt+N to move
>>> on to the next window. Once I get that working, it should be
>>> downhill from there. The code will likely look familiar to people
>>> out there - it's been the result of my searching the Internet for
>>> just how to do this.
>>>
>>> I'll follow with my code and error message below.
>>> #####
>>> Code
>>> #####
>>> $domain = [AppDomain]::CurrentDomain
>>> $name = New-Object Reflection.AssemblyName
>>> 'PInvokeFindWindowAssembly' $assembly =
>>> $domain.DefineDynamicAssembly($name, 'Run') $FindWindowmodule =
>>> $assembly.DefineDynamicModule('PInvokeFindWindowModule')
>>> $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
>>> [Type[]]$FindWindowparameterTypes = [string], [string]
>>> $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
>>> 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
>>> $Constructor =
>>> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]
>>> ) $FindWindowattr = New-Object
>>> Reflection.Emit.CustomAttributeBuilder $Constructor, 'user32'
>>> $FindWindowmethod.SetCustomAttribute($FindWindowattr)
>>> $realFindWindowType = $FindWindowtype.CreateType()
>>> [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
>>>
>>> [IntPtr]$FoundWindow =
>>> $realFindWindowType.InvokeMember('FindWindow',
>>> 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
>>>
>>> $name = New-Object Reflection.AssemblyName
>>> 'PInvokeSendMessageAssembly'
>>> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
>>> $SendMessagemodule =
>>> $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
>>> $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
>>> [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32],
>>> [Int32]
>>> $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
>>> 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
>>> $Constructor =
>>> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]
>>> )
>>> $SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
>>> $Constructor, 'user32'
>>> $SendMessagemethod.SetCustomAttribute($SendMessageattr)
>>> $realSendMessageType = $SendMessagetype.CreateType()
>>> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
>>> [Int32]0x00000012, [Int32]0x20380001
>>> $realSendMessageType.InvokeMember('SendMessage',
>>> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>>> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
>>> [Int32]0x00000009, [Int32]0xa00f0001
>>>
>>> $realSendMessageType.InvokeMember('SendMessage',
>>> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>>> #####
>>> Errors
>>> #####
>>> PS F:\PowerShell Scripts\Automated Installs - Install Pearson
>>> CourseCompass>
>>> .\
>>> endMessage.ps1
>>> Exception calling "InvokeMember" with "5" argument(s): "Method
>>> 'PInvokeSendMess
>>> ageType.SendMessage' not found."
>>> At F:\PowerShell Scripts\Automated Installs - Install Pearson
>>> CourseCompass\Sen
>>> dMessage.ps1:38 char:34
>>> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
>>> 'Public,Static,InvokeM
>>> ethod', $null, $null, $SendMessageargs)
>>> Exception calling "InvokeMember" with "5" argument(s): "Method
>>> 'PInvokeSendMess
>>> ageType.SendMessage' not found."
>>> At F:\PowerShell Scripts\Automated Installs - Install Pearson
>>> CourseCompass\Sen
>>> dMessage.ps1:42 char:34
>>> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
>>> 'Public,Static,InvokeM
>>> ethod', $null, $null, $SendMessageargs)
>>> #####
>>> Parting Message
>>> #####
>>> I'm more of a scripter than a programmer (I can't claim to know .Net
>>> by any means) so I'm hoping the answer is failry obvious. Hopefully
>>> a
>>> second pair of eyes is all it will take.
>>> Thanks!
>>>
>>> Bill
>>>

My System SpecsSystem Spec
Old 11-29-2007   #9 (permalink)
Bill V.


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

Part of the problem is that I can't bring a window into focus. One of the
goals is to be able to run the script regardless of if someone is logged in
or not. To have a window in focus, I have to have someone logged in. Since
I ultimately want to have the script as a weekly scheduled task (it will
ultimately be able to perform weekly scheduled tasks, or updates if they come
along), it would be much cleaner to have it be able to run completely in the
background than to have to have the computers logged in as someone.

That's why I've been so stubborn . I actually already have vbscripts that
will perform the install (at least for this particular application - part of
why I was messing with this one early on in the process. It was the messiest
install I commonly make. But using sendkeys is always messy, and doesn't
always work well, even if I try to continually bring the window back into
focus). But, if I can send messages directly to the window, then it shoudn't
even matter if I can never bring the window into focus.

Thanks

-Bill

"Shay Levi" wrote:
Quote:

> From my exprience, clicking on unfocused window control shouldn't be a problem,
> use the ControlClick function
>
> ControlClick ( "title", "text", controlID [, button] [, clicks]] )
>
>
> Here's a test:
>
> Open a few explorer windows, then execute this in AutoIt:
>
> Run("control desk.cpl")
> WinWait("Display Properties")
> Sleep(3000)
> ; now manually, click another window to make it the active window
> ControlClick ( "Display Properties", "", "Button1")
> ; you should see the "Save As" dialog
>
>
> HTH
>
> -----
> Shay Levi
> $cript Fanatic
> http://scriptolog.blogspot.com
> Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic
>
>
>
Quote:

> > You're the second person to mention that article (in nearly as many
> > minutes).
> > I'm planning on looking the cmd-lets over (when I get home) and I'll
> > see if
> > it helps me any. It certainly would be a cleaner way to get things
> > working.
> > Ironically, I checked out AutoIt earlier this month (I've been working
> > on this problem off an on for a while - I've just finally gotten the
> > chance to pick it back up again). It looked like it suffered from the
> > same problem I had with sendkeys - you had to be logged in for things
> > to function properly. I asked around in the genral forum if it could
> > send messages to out of focus apps, but I never got a response (and i
> > got back to work and hadn't gotten back to things since then).
> >
> > Thanks
> > -Bill
> > "Shay Levi" wrote:
> >
Quote:

> >> IMO, AutoIt is your friend. Writing this kind of automations in
> >> PowerShell
> >> can be quiet a challenge.
> >> Few days ago I blogged on a new set of Cmdlets, byDr. James
> >> McCaffrey, designed
> >> to perform Windows UI automation tasks
> >> http://msdn.microsoft.com/msdnmag/is...n/default.aspx
> >> Anyway, for now, AutoIt can perform a wide range of GUI automations,
> >> and
> >> based on my own expreince, its the
> >> best GUI automation tool I've know. You can get more info on
> >> http://www.autoitscript.com/autoit3.
> >> -----
> >> Shay Levi
> >> $cript Fanatic
> >> http://scriptolog.blogspot.com
> >> Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic
> >>> Hello everyone.
> >>>
> >>> I'm fairly new to Powershell (as is nearly everyone, I imagine) and
> >>> I'm just starting to get my feet wet. And, what better way to learn
> >>> a new language than to attempt to tackle an insanely complicated
> >>> process!
> >>>
> >>> I'm a PC Tech at a college who is trying to make my life easier by
> >>> automating software installs (rather than keeping several ghost
> >>> images for each computer type, my ultimate goal is to keep clean
> >>> images of basic computer models, and use automation to install the
> >>> software required on the computers. I also want to schedule the
> >>> script to perform regular updates as well, but that's some ways off
> >>> yet - I'd be happy with it running through once). Quite a bit of
> >>> the educational software out there is, to be blunt, poorly written -
> >>> at least regarding their installers. Typically, there are no
> >>> command line options for installed software, just keystrokes and
> >>> mouse clicks in the gui provided. I'm trying to automate this,
> >>> without using sendkeys - Ideally the script should be able to run
> >>> whether someone is logged on or not - an option I don't have with
> >>> sendkeys. (Not to mention the basic problems of applications
> >>> loosing focus even if someone is logged in.)
> >>>
> >>> However, all is not lost - it looks like FindWindow and SendMessage
> >>> could be the answer to my prayers, if I could only get them to work.
> >>> (from what I gather, I can send messages to the window, even if
> >>> no one is currently logged on - exactly what I'm looking for)
> >>> Actually, I have FindWindow working, but I can't get SendMessage to
> >>> run properly. Right now, I can find the window I'm looking for
> >>> (Window type '#32770' - an Install Shield window, with a name
> >>> of"Welcome"). All, I'm trying to do currently is hit Alt+N to move
> >>> on to the next window. Once I get that working, it should be
> >>> downhill from there. The code will likely look familiar to people
> >>> out there - it's been the result of my searching the Internet for
> >>> just how to do this.
> >>>
> >>> I'll follow with my code and error message below.
> >>> #####
> >>> Code
> >>> #####
> >>> $domain = [AppDomain]::CurrentDomain
> >>> $name = New-Object Reflection.AssemblyName
> >>> 'PInvokeFindWindowAssembly' $assembly =
> >>> $domain.DefineDynamicAssembly($name, 'Run') $FindWindowmodule =
> >>> $assembly.DefineDynamicModule('PInvokeFindWindowModule')
> >>> $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
> >>> [Type[]]$FindWindowparameterTypes = [string], [string]
> >>> $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
> >>> 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
> >>> $Constructor =
> >>> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]
> >>> ) $FindWindowattr = New-Object
> >>> Reflection.Emit.CustomAttributeBuilder $Constructor, 'user32'
> >>> $FindWindowmethod.SetCustomAttribute($FindWindowattr)
> >>> $realFindWindowType = $FindWindowtype.CreateType()
> >>> [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
> >>>
> >>> [IntPtr]$FoundWindow =
> >>> $realFindWindowType.InvokeMember('FindWindow',
> >>> 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
> >>>
> >>> $name = New-Object Reflection.AssemblyName
> >>> 'PInvokeSendMessageAssembly'
> >>> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
> >>> $SendMessagemodule =
> >>> $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
> >>> $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
> >>> [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32],
> >>> [Int32]
> >>> $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
> >>> 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
> >>> $Constructor =
> >>> [Runtime.InteropServices.DllImportAttribute].GetConstructor([string]
> >>> )
> >>> $SendMessageattr = New-Object Reflection.Emit.CustomAttributeBuilder
> >>> $Constructor, 'user32'
> >>> $SendMessagemethod.SetCustomAttribute($SendMessageattr)
> >>> $realSendMessageType = $SendMessagetype.CreateType()
> >>> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
> >>> [Int32]0x00000012, [Int32]0x20380001
> >>> $realSendMessageType.InvokeMember('SendMessage',
> >>> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
> >>> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
> >>> [Int32]0x00000009, [Int32]0xa00f0001
> >>>
> >>> $realSendMessageType.InvokeMember('SendMessage',
> >>> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
> >>> #####
> >>> Errors
> >>> #####
> >>> PS F:\PowerShell Scripts\Automated Installs - Install Pearson
> >>> CourseCompass>
> >>> .\
> >>> endMessage.ps1
> >>> Exception calling "InvokeMember" with "5" argument(s): "Method
> >>> 'PInvokeSendMess
> >>> ageType.SendMessage' not found."
> >>> At F:\PowerShell Scripts\Automated Installs - Install Pearson
> >>> CourseCompass\Sen
> >>> dMessage.ps1:38 char:34
> >>> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> >>> 'Public,Static,InvokeM
> >>> ethod', $null, $null, $SendMessageargs)
> >>> Exception calling "InvokeMember" with "5" argument(s): "Method
> >>> 'PInvokeSendMess
> >>> ageType.SendMessage' not found."
> >>> At F:\PowerShell Scripts\Automated Installs - Install Pearson
> >>> CourseCompass\Sen
> >>> dMessage.ps1:42 char:34
> >>> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
> >>> 'Public,Static,InvokeM
> >>> ethod', $null, $null, $SendMessageargs)
> >>> #####
> >>> Parting Message
> >>> #####
> >>> I'm more of a scripter than a programmer (I can't claim to know .Net
> >>> by any means) so I'm hoping the answer is failry obvious. Hopefully
> >>> a
> >>> second pair of eyes is all it will take.
> >>> Thanks!
> >>>
> >>> Bill
> >>>
>
>
>
My System SpecsSystem Spec
Old 11-29-2007   #10 (permalink)
Shay Levi


 
 

Re: Win32 API's in Powershell - FindWindow and SendMessage

Bill,

I can't tell for sure what happens when no one is logged on. What I do know
is that you can send any mouse click
or keystrock to any windows whether it's active (in focus) or not (using
AutoIt).

Can you point me to your post in AutoIt forums?


-----
Shay Levi
$cript Fanatic
http://scriptolog.blogspot.com
Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic


Quote:

> Part of the problem is that I can't bring a window into focus. One of
> the goals is to be able to run the script regardless of if someone is
> logged in or not. To have a window in focus, I have to have someone
> logged in. Since I ultimately want to have the script as a weekly
> scheduled task (it will ultimately be able to perform weekly scheduled
> tasks, or updates if they come along), it would be much cleaner to
> have it be able to run completely in the background than to have to
> have the computers logged in as someone.
>
> That's why I've been so stubborn . I actually already have
> vbscripts that will perform the install (at least for this particular
> application - part of why I was messing with this one early on in the
> process. It was the messiest install I commonly make. But using
> sendkeys is always messy, and doesn't always work well, even if I try
> to continually bring the window back into focus). But, if I can send
> messages directly to the window, then it shoudn't even matter if I can
> never bring the window into focus.
>
> Thanks
>
> -Bill
>
> "Shay Levi" wrote:
>
Quote:

>> From my exprience, clicking on unfocused window control shouldn't be
>> a problem, use the ControlClick function
>>
>> ControlClick ( "title", "text", controlID [, button] [, clicks]] )
>>
>> Here's a test:
>>
>> Open a few explorer windows, then execute this in AutoIt:
>>
>> Run("control desk.cpl")
>> WinWait("Display Properties")
>> Sleep(3000)
>> ; now manually, click another window to make it the active window
>> ControlClick ( "Display Properties", "", "Button1")
>> ; you should see the "Save As" dialog
>> HTH
>>
>> -----
>> Shay Levi
>> $cript Fanatic
>> http://scriptolog.blogspot.com
>> Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic
Quote:

>>> You're the second person to mention that article (in nearly as many
>>> minutes).
>>> I'm planning on looking the cmd-lets over (when I get home) and I'll
>>> see if
>>> it helps me any. It certainly would be a cleaner way to get things
>>> working.
>>> Ironically, I checked out AutoIt earlier this month (I've been
>>> working
>>> on this problem off an on for a while - I've just finally gotten the
>>> chance to pick it back up again). It looked like it suffered from
>>> the
>>> same problem I had with sendkeys - you had to be logged in for
>>> things
>>> to function properly. I asked around in the genral forum if it
>>> could
>>> send messages to out of focus apps, but I never got a response (and
>>> i
>>> got back to work and hadn't gotten back to things since then).
>>> Thanks
>>> -Bill
>>> "Shay Levi" wrote:
>>>> IMO, AutoIt is your friend. Writing this kind of automations in
>>>> PowerShell
>>>> can be quiet a challenge.
>>>> Few days ago I blogged on a new set of Cmdlets, byDr. James
>>>> McCaffrey, designed
>>>> to perform Windows UI automation tasks
>>>> http://msdn.microsoft.com/msdnmag/is...n/default.aspx
>>>> Anyway, for now, AutoIt can perform a wide range of GUI
>>>> automations,
>>>> and
>>>> based on my own expreince, its the
>>>> best GUI automation tool I've know. You can get more info on
>>>> http://www.autoitscript.com/autoit3.
>>>> -----
>>>> Shay Levi
>>>> $cript Fanatic
>>>> http://scriptolog.blogspot.com
>>>> Hebrew weblog: http://blogs.microsoft.co.il/blogs/scriptfanatic
>>>>> Hello everyone.
>>>>>
>>>>> I'm fairly new to Powershell (as is nearly everyone, I imagine)
>>>>> and I'm just starting to get my feet wet. And, what better way to
>>>>> learn a new language than to attempt to tackle an insanely
>>>>> complicated process!
>>>>>
>>>>> I'm a PC Tech at a college who is trying to make my life easier by
>>>>> automating software installs (rather than keeping several ghost
>>>>> images for each computer type, my ultimate goal is to keep clean
>>>>> images of basic computer models, and use automation to install the
>>>>> software required on the computers. I also want to schedule the
>>>>> script to perform regular updates as well, but that's some ways
>>>>> off yet - I'd be happy with it running through once). Quite a bit
>>>>> of the educational software out there is, to be blunt, poorly
>>>>> written - at least regarding their installers. Typically, there
>>>>> are no command line options for installed software, just
>>>>> keystrokes and mouse clicks in the gui provided. I'm trying to
>>>>> automate this, without using sendkeys - Ideally the script should
>>>>> be able to run whether someone is logged on or not - an option I
>>>>> don't have with sendkeys. (Not to mention the basic problems of
>>>>> applications loosing focus even if someone is logged in.)
>>>>>
>>>>> However, all is not lost - it looks like FindWindow and
>>>>> SendMessage could be the answer to my prayers, if I could only get
>>>>> them to work. (from what I gather, I can send messages to the
>>>>> window, even if no one is currently logged on - exactly what I'm
>>>>> looking for) Actually, I have FindWindow working, but I can't get
>>>>> SendMessage to run properly. Right now, I can find the window I'm
>>>>> looking for (Window type '#32770' - an Install Shield window, with
>>>>> a name of"Welcome"). All, I'm trying to do currently is hit Alt+N
>>>>> to move on to the next window. Once I get that working, it should
>>>>> be downhill from there. The code will likely look familiar to
>>>>> people out there - it's been the result of my searching the
>>>>> Internet for just how to do this.
>>>>>
>>>>> I'll follow with my code and error message below.
>>>>> #####
>>>>> Code
>>>>> #####
>>>>> $domain = [AppDomain]::CurrentDomain
>>>>> $name = New-Object Reflection.AssemblyName
>>>>> 'PInvokeFindWindowAssembly' $assembly =
>>>>> $domain.DefineDynamicAssembly($name, 'Run') $FindWindowmodule =
>>>>> $assembly.DefineDynamicModule('PInvokeFindWindowModule')
>>>>> $FindWindowtype = $FindWindowmodule.DefineType('PInvokeType')
>>>>> [Type[]]$FindWindowparameterTypes = [string], [string]
>>>>> $FindWindowmethod = $FindWindowtype.DefineMethod('FindWindow',
>>>>> 'Public,Static,PinvokeImpl', [int], $FindWindowparameterTypes)
>>>>> $Constructor =
>>>>> [Runtime.InteropServices.DllImportAttribute].GetConstructor([strin
>>>>> g]
>>>>> ) $FindWindowattr = New-Object
>>>>> Reflection.Emit.CustomAttributeBuilder $Constructor, 'user32'
>>>>> $FindWindowmethod.SetCustomAttribute($FindWindowattr)
>>>>> $realFindWindowType = $FindWindowtype.CreateType()
>>>>> [object[]]$FindWindowargs = [string] '#32770', [string] "Welcome"
>>>>> [IntPtr]$FoundWindow =
>>>>> $realFindWindowType.InvokeMember('FindWindow',
>>>>> 'Public,Static,InvokeMethod', $null, $null, $FindWindowargs)
>>>>> $name = New-Object Reflection.AssemblyName
>>>>> 'PInvokeSendMessageAssembly'
>>>>> $assembly = $domain.DefineDynamicAssembly($name, 'Run')
>>>>> $SendMessagemodule =
>>>>> $assembly.DefineDynamicModule('PInvokeSendMsgeModule')
>>>>> $SendMessagetype = $SendMessagemodule.DefineType('PInvokeType')
>>>>> [Type[]]$SendMessageparameterType = [IntPtr], [Int32], [Int32],
>>>>> [Int32]
>>>>> $SendMessagemethod = $SendMessagetype.DefineMethod("SendMessage",
>>>>> 'Public,Static,PinvokeImpl', [int], $SendMessageparameterTypes)
>>>>> $Constructor =
>>>>> [Runtime.InteropServices.DllImportAttribute].GetConstructor([strin
>>>>> g]
>>>>> )
>>>>> $SendMessageattr = New-Object
>>>>> Reflection.Emit.CustomAttributeBuilder
>>>>> $Constructor, 'user32'
>>>>> $SendMessagemethod.SetCustomAttribute($SendMessageattr)
>>>>> $realSendMessageType = $SendMessagetype.CreateType()
>>>>> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]100,
>>>>> [Int32]0x00000012, [Int32]0x20380001
>>>>> $realSendMessageType.InvokeMember('SendMessage',
>>>>> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>>>>> [object[]]$SendMessageargs = [IntPtr]$FoundWindow, [Int32]104,
>>>>> [Int32]0x00000009, [Int32]0xa00f0001
>>>>> $realSendMessageType.InvokeMember('SendMessage',
>>>>> 'Public,Static,InvokeMethod', $null, $null, $SendMessageargs)
>>>>> #####
>>>>> Errors
>>>>> #####
>>>>> PS F:\PowerShell Scripts\Automated Installs - Install Pearson
>>>>> CourseCompass>
>>>>> .\
>>>>> endMessage.ps1
>>>>> Exception calling "InvokeMember" with "5" argument(s): "Method
>>>>> 'PInvokeSendMess
>>>>> ageType.SendMessage' not found."
>>>>> At F:\PowerShell Scripts\Automated Installs - Install Pearson
>>>>> CourseCompass\Sen
>>>>> dMessage.ps1:38 char:34
>>>>> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
>>>>> 'Public,Static,InvokeM
>>>>> ethod', $null, $null, $SendMessageargs)
>>>>> Exception calling "InvokeMember" with "5" argument(s): "Method
>>>>> 'PInvokeSendMess
>>>>> ageType.SendMessage' not found."
>>>>> At F:\PowerShell Scripts\Automated Installs - Install Pearson
>>>>> CourseCompass\Sen
>>>>> dMessage.ps1:42 char:34
>>>>> + $realSendMessageType.InvokeMember( <<<< 'SendMessage',
>>>>> 'Public,Static,InvokeM
>>>>> ethod', $null, $null, $SendMessageargs)
>>>>> #####
>>>>> Parting Message
>>>>> #####
>>>>> I'm more of a scripter than a programmer (I can't claim to know
>>>>> .Net
>>>>> by any means) so I'm hoping the answer is failry obvious.
>>>>> Hopefully
>>>>> a
>>>>> second pair of eyes is all it will take.
>>>>> Thanks!
>>>>> Bill
>>>>>

My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
[ultimate geek] api's, typedef's, Forms (gui interface) -- from script VB Script
[ann] another way to call api's from script (the PB way) VB Script
Win32 help Vista installation & setup
Accessing System 32 and COM API's for Vista thru Powershell PowerShell


Vista Forums 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 Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46