0

In vb.net I'm trying to find a reliable way to start a new process in a hidden, minimized, normal, or maximized window (as determined ahead of time by the user).

The following code, with the value of MyWindowProcessingStyle appropriately set, works sometimes but not others:

     Dim MyWindowsProcessingStyle As ProcessWindowStyle = ProcessWindowStyle.Maximized

    ' the above set elsewhere to values of minimized, maximized, hidden, and normal

    Dim MyProcess as new Process
    Dim MyProcessStartInfo As New ProcessStartInfo

    With MyProcessStartInfo
         .FileName = Program
         .Verb = "open"
         .CreateNoWindow = True               
         .WindowStyle = MyWindowProcessingStyle
         .UseShellExecute = True
    End With

    myProcess.Start(MyProcessStartInfo)

For example, if I use it to start a batch file (.bat) it works reliably 100% of the time.

If however, I use it to start the window's calculator it does not really work at all. It just opens the window's calculator in the same way it was last run.

I need to stay with the other parts in the MyProcessStartInfo for reasons related to how my app works. Accordingly, this observation is no good for me.

I've tried to send keystrokes to the application, after it starts, for example (WIN)(DownArrrow) to minimize the application after the fact - and while this works in many cases it is problematic and flaky in others.

I've also tried to get the process ID or the handle of app once it has started, in the hopes that I could use various Pinvolke methods after that to get what I'm after - but I have sadly failed in that.

Any help would be very much appreciated.

Rob
  • 3,488
  • 3
  • 32
  • 27
  • You can show a new Windowed process with a `WindowStyle` you pre-define. For example, Notepad can be run `Hidden` using `CreateNoWindow = False` and `UseShellExecute = True`. But not all applications respond to this well. Calc.exe (and other Windows applets), restore their Window after you have executed them. – Jimi Jan 10 '19 at 00:11
  • You could use UIAutomation though. A [WindowPattern.WindowOpenedEvent](https://learn.microsoft.com/en-us/dotnet/api/system.windows.automation.windowpattern.windowopenedevent) can detect the activation of any Windowed process in the system. When the event is raised, its `source` member will give you the Main Window Element object, which you can then automate as required (most of the time). – Jimi Jan 10 '19 at 01:23
  • ok so that sent me down the rabbit hole for an hour :-) - I translated the code in the link into vb.net, but in my scenario, I'm not sure what the target control automation element is or how to reference it when calling the registrationforautomationevents subroutine. would appreciate your insights – Rob Jan 10 '19 at 02:57
  • What do you mean with *translated*? Didn't you click (upper right corner of the page) on the language selector? You can pick VB.Net as the current code language -- When you register an Automation event: `Automation.AddAutomationEventHandler` using the `WindowPattern.WindowOpenedEvent`, the target `AutomatinElement` is a `null` one (usually a class Field: `private targetElement as AutomationElement = nothing`). When you receive the event, you cast the `sender` object to `targetElement`: `targetElement = DirectCast(source, AutomationElement)`. – Jimi Jan 10 '19 at 06:02
  • Well, if you want I'll post a code sample about this. Btw, I've already posted something strictly related in VB.Net here: [Add an event to all Forms in a Project](https://stackoverflow.com/a/51505218/7444103) (and also elsewhere here in SO, I think). As a note, you can minimize/maximize a Window with UI Automation, but you cannot hide it or move it completely off-screen. Because this defeats the purpose of Automation (at least in the Accessibility-bound terms defined by Microsoft) – Jimi Jan 10 '19 at 06:02
  • Hi Jimi, thanks very much. I didn't see the language selector, that would have made the job easier :-). Regardless, when I used that copied code with targetElement as AutomationElement = nothing - it threw an error value cannot be null for the open event handler, so I tried " targetElement As AutomationElement = AutomationElement.RootElement " and while that seemed to allow the event handler to be created, the event did not fire when I opened a window. – Rob Jan 10 '19 at 12:24
  • I will look at your code that you linked to in more detail tonight, but a sample would be great as this sounds to be exactly what I am after. Thanks again for your help. – Rob Jan 10 '19 at 12:24
  • Yes, of course, when adding a new Event Handler, that **Field** has no value. It will be used to assign the object that the Handler returns. I suggested to use a field because that value will constantly change and you might need to use it somewhere else. Anyway, I'll post an example on how to *handle* a Process' Window creation/destruction detection and how to modify the Window status/position. – Jimi Jan 10 '19 at 19:38
  • 1
    Hi Jimi, thanks again for your help. I believe I have it all worked out now. The example code was using treescope.element and I needed treescope.children. After I realized that, with the help you had already provided and some other posts, I figured all the rest out. No need to post an example for me. I very much appreciate your help - you're the man! – Rob Jan 11 '19 at 03:08
  • Well, you're welcome! I thought I could to post the code earlier, but, well, busy day. Anyway, if you need a hand, let me know. – Jimi Jan 11 '19 at 03:25

0 Answers0