Restrict a main window of a process to a set screen area with PowerShell

Viewing 30 reply threads
  • Author
    Posts
    • #1559580
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Hello all,
      I have a little project that I’m hoping I can do in PowerShell. There are other ways of achieving what I want to do but I also want to learn a bit more about PS and thus a little project is what I need. However I could do with a nudge in the right direction if anyone has some handy hints or pointers to where I can read up on solutions to my problems.

      I’m trying to write a bit of script that will start a number of processes (four probably) it will size the main window or each process and position them on the screen. I know I could start them then use hotkeys or Snap Assist but I want these applications to be contained in their allotted screen space. Thus if someone presses maximize the app will only go up to the limits of the screen area I’ve set and not the whole available screen.

      A possible way of doing this that I’ve thought of is use PS to produce a windows form with panels on it of the right shape and position. I would then start the process inside the panel and thus contain it. I can make the forms and panels no problem it’s the starting the process in the form which is eluding me at the moment. I’ve seen it done in C# but not sure how to convert it over to PS. Does anyone have any tips ? or maybe another way to do it in PS that I haven’t thought of ? Thanks for reading.

      avatar
    • #1559635
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      What kind of processes are they?  It’s still the same controls?

      David F.

    • #1559636
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Hello David F.  The application is a thing called Pi Processbook made by a company called OSIsoft.  It looks to be a standard type interface with normal window form type controls.  Another complication is I’ll be wanting to do it with with application being hosted on a Citrix server but one step at a time..

    • #1559637
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      The Citrix part really shouldn’t matter.  The user processes are completely isolated from each other other.  The only real issue could be if you have common files being written to (typical Citrix issue).

      If they are all launched from the parent process running your Forms/WPF, and the generated windows live within the controls(?), it should work just fine.

       

      David F.

    • #1559638
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Hello David,  I have run in to problems with Citrix before in the manner you’ve outlined but that’s another days problem.

      Good you think the main part of my project should work OK,

      Would you have any pointers as to how I can achieve this ? Maybe an example on line somewhere to get me started. Like I said in my opener the basics of making a form and panels , buttons etc I’m ok with in PS but I need to do a lot more reading . I have scoured the google achieve and searched with every combination of words I can think of but alas nothing has popped up..

    • #1559640
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      Well, again, most of this is theoretical. But, from a PS point of view, you can generally get the window information with Get-Process.

      Here’s an example I found online for this kind of window manipulation.

      https://superuser.com/questions/1324007/setting-window-size-and-position-in-powershell-5-and-6

       

      Function Set-Window {
      <#
      .SYNOPSIS
      Retrieve/Set the window size and coordinates of a process window.
      
      .DESCRIPTION
      Retrieve/Set the size (height,width) and coordinates (x,y) 
      of a process window.
      
      .PARAMETER ProcessName
      Name of the process to determine the window characteristics. 
      (All processes if omitted).
      
      .PARAMETER Id
      Id of the process to determine the window characteristics. 
      
      .PARAMETER X
      Set the position of the window in pixels from the left.
      
      .PARAMETER Y
      Set the position of the window in pixels from the top.
      
      .PARAMETER Width
      Set the width of the window.
      
      .PARAMETER Height
      Set the height of the window.
      
      .PARAMETER Passthru
      Returns the output object of the window.
      
      .NOTES
      Name:   Set-Window
      Author: Boe Prox
      Version History:
          1.0//Boe Prox - 11/24/2015 - Initial build
          1.1//JosefZ   - 19.05.2018 - Treats more process instances 
                                       of supplied process name properly
          1.2//JosefZ   - 21.02.2019 - Parameter Id
      
      .OUTPUTS
      None
      System.Management.Automation.PSCustomObject
      System.Object
      
      .EXAMPLE
      Get-Process powershell | Set-Window -X 20 -Y 40 -Passthru -Verbose
      VERBOSE: powershell (Id=11140, Handle=132410)
      
      Id          : 11140
      ProcessName : powershell
      Size        : 1134,781
      TopLeft     : 20,40
      BottomRight : 1154,821
      
      Description: Set the coordinates on the window for the process PowerShell.exe
      
      .EXAMPLE
      $windowArray = Set-Window -Passthru
      WARNING: cmd (1096) is minimized! Coordinates will not be accurate.
      
          PS C:\>$windowArray | Format-Table -AutoSize
      
        Id ProcessName    Size     TopLeft       BottomRight  
        -- -----------    ----     -------       -----------  
      1096 cmd            199,34   -32000,-32000 -31801,-31966
      4088 explorer       1280,50  0,974         1280,1024    
      6880 powershell     1280,974 0,0           1280,974     
      
      Description: Get the coordinates of all visible windows and save them into the
                   $windowArray variable. Then, display them in a table view.
      
      .EXAMPLE
      Set-Window -Id $PID -Passthru | Format-Table
      ​‌‍
        Id ProcessName Size     TopLeft BottomRight
        -- ----------- ----     ------- -----------
      7840 pwsh        1024,638 0,0     1024,638
      
      Description: Display the coordinates of the window for the current 
                   PowerShell session in a table view.
      
      #>
      [cmdletbinding(DefaultParameterSetName='Name')]
      Param (
          [parameter(Mandatory=$False,
              ValueFromPipelineByPropertyName=$True, ParameterSetName='Name')]
          [string]$ProcessName='*',
          [parameter(Mandatory=$True,
              ValueFromPipeline=$False,              ParameterSetName='Id')]
          [int]$Id,
          [int]$X,
          [int]$Y,
          [int]$Width,
          [int]$Height,
          [switch]$Passthru
      )
      Begin {
          Try { 
              [void][Window]
          } Catch {
          Add-Type @"
              using System;
              using System.Runtime.InteropServices;
              public class Window {
              [DllImport("user32.dll")]
              [return: MarshalAs(UnmanagedType.Bool)]
              public static extern bool GetWindowRect(
                  IntPtr hWnd, out RECT lpRect);
      
              [DllImport("user32.dll")]
              [return: MarshalAs(UnmanagedType.Bool)]
              public extern static bool MoveWindow( 
                  IntPtr handle, int x, int y, int width, int height, bool redraw);
      
              [DllImport("user32.dll")] 
              [return: MarshalAs(UnmanagedType.Bool)]
              public static extern bool ShowWindow(
                  IntPtr handle, int state);
              }
              public struct RECT
              {
              public int Left;        // x position of upper-left corner
              public int Top;         // y position of upper-left corner
              public int Right;       // x position of lower-right corner
              public int Bottom;      // y position of lower-right corner
              }
      "@
          }
      }
      Process {
          $Rectangle = New-Object RECT
          If ( $PSBoundParameters.ContainsKey('Id') ) {
              $Processes = Get-Process -Id $Id -ErrorAction SilentlyContinue
          } else {
              $Processes = Get-Process -Name "$ProcessName" -ErrorAction SilentlyContinue
          }
          if ( $null -eq $Processes ) {
              If ( $PSBoundParameters['Passthru'] ) {
                  Write-Warning 'No process match criteria specified'
              }
          } else {
              $Processes | ForEach-Object {
                  $Handle = $_.MainWindowHandle
                  Write-Verbose "$($_.ProcessName) `(Id=$($_.Id), Handle=$Handle)"
                  if ( $Handle -eq [System.IntPtr]::Zero ) { return }
                  $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle)
                  If (-NOT $PSBoundParameters.ContainsKey('X')) {
                      $X = $Rectangle.Left            
                  }
                  If (-NOT $PSBoundParameters.ContainsKey('Y')) {
                      $Y = $Rectangle.Top
                  }
                  If (-NOT $PSBoundParameters.ContainsKey('Width')) {
                      $Width = $Rectangle.Right - $Rectangle.Left
                  }
                  If (-NOT $PSBoundParameters.ContainsKey('Height')) {
                      $Height = $Rectangle.Bottom - $Rectangle.Top
                  }
                  If ( $Return ) {
                      $Return = [Window]::MoveWindow($Handle, $x, $y, $Width, $Height,$True)
                  }
                  If ( $PSBoundParameters['Passthru'] ) {
                      $Rectangle = New-Object RECT
                      $Return = [Window]::GetWindowRect($Handle,[ref]$Rectangle)
                      If ( $Return ) {
                          $Height      = $Rectangle.Bottom - $Rectangle.Top
                          $Width       = $Rectangle.Right  - $Rectangle.Left
                          $Size        = New-Object System.Management.Automation.Host.Size        -ArgumentList $Width, $Height
                          $TopLeft     = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Left , $Rectangle.Top
                          $BottomRight = New-Object System.Management.Automation.Host.Coordinates -ArgumentList $Rectangle.Right, $Rectangle.Bottom
                          If ($Rectangle.Top    -lt 0 -AND 
                              $Rectangle.Bottom -lt 0 -AND
                              $Rectangle.Left   -lt 0 -AND
                              $Rectangle.Right  -lt 0) {
                              Write-Warning "$($_.ProcessName) ($($_.Id)`) is minimized! Coordinates will not be accurate."
                          }
                          $Object = [PSCustomObject]@{
                              Id          = $_.Id
                              ProcessName = $_.ProcessName
                              Size        = $Size
                              TopLeft     = $TopLeft
                              BottomRight = $BottomRight
                          }
                          $Object
                      }
                  }
              }
          }
      }
      }

      So, the theory is you grab the window parameters for your application as it starts, and use something like this function to move it within your predefined panels.

      Ultimately, AutoIT is better for this than PS.. but it should be possible.

       

      David F.

      avatar
    • #1559641
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Thanks David, I’ll trya and absorb that example over the next couple of days and hopefully the light will turn on and I’ll be away…

    • #1559659
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Hello again David.. I’m probably missing something here as I must admit to being a bit guessy.  I can probably get to the point (using the above) of starting an application and sizing/moving it on the screen but still can’t make it run inside a panel on a form and maybe I don’t need to. My goal it to ensure if someone clicks maximize or tries to move a window manually then it can only happen within a set screen area. At the moment I can start four instances of the application and arrange them manually just nice and lovely. Someone will open a new one or press maximize on one of them and it’ll cover the whole screen and in them trying to get it back to the right size they will end up making the display unusable for all. It is a common screen and people need to be able to interact with the displays..

      I haven’t done anything with AutoIT before but giving it a quick read it looks like it does a lot of the heavy lifting for you.  Do you think AutoIt could do what I need ? and if so any suggestions as to how ? As mentioned restricting the screen space for each instance of the app is where I’m trying to end up..

       

      Thanks for your help and suggestions thus far David…

    • #1559681
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      I’m reasonably sure AutoIT can do it.

      Overall, I’d think you’d want to monitor for a few things:

      1. Process count for the application’s main executable to keep it under 4
      2. When you launch the process, tell the application that the screen real estate is limited to the size you tell it.  That should make it easier to control where goes.
        1. When you launch the process with AutoIT, you’ll get the PID, and the Window handle, which will let you do pretty much everything you need.
      3. I *believe* you should be able to enforce a maximum size on the windows and I know you can disable the min & max buttons with it

      And for what it’s worth about 80% of the AutoIT commands can be done with the AutoIT Powershell module.

      Good luck!

      David F.

    • #1559696
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Hello David, I’m really sorry to harass you like this but I’m not really getting anywhere.  I can do the open and move stuff about after taking on board you comments and reading the post you linked but the crucial bit for my application is the “enforce a maximum size on the window” I can’t fathom.  As mentioned I don’t really care if I have to start the application in a container of some sorts (like in a panel on a win form)  or control its maximum some other way either directly or not but I do need to set its maximum size it goes to if someone presses the maximize button.  Even if I knew if this is possible or not would be a help I guess.

      so thanks again for your continued assistance..

    • #1559703
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      And you’re definitely seeing why I recommended AutoIT – there’s much better facilities for handling this kind of thing.

      But the API snippet should be this:

      case WM_GETMINMAXINFO:
      {
          LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
          lpMMI->ptMinTrackSize.x = 300;
          lpMMI->ptMinTrackSize.y = 300;
      }

      I got that from StackOverflow: https://stackoverflow.com/questions/22261804/how-to-set-minimum-window-size-using-winapi which of course led to the MSDN docs 🙂
      https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-getminmaxinfo?redirectedfrom=MSDN

       

      David F.

      avatar
    • #1559704
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Oh yes I’m definitely seeing the advantages of AutoIt I’ve been YouTube binging on it and it is certainly the easiest tool for many tasks. The fact it’s portable and contains a real easy to use EXE maker means it will be my go to for some thing. So thanks for that David I’ve leant a lot by coming on this forum already..

      Now to eagerly digest your posts about window restrictions… Happy Christmas to whomever reads this post.. 🙂

    • #1559705
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      I think I understand how it is meant to work but hmmm it’s not. I must have something fundamental wrong with my code below.

      I start up the notepad app.

      I grab the winhandle for it using WinGetHandle.

      I then set up a dll structure and populate it with some data…

      All this is going well so far 🙂

      I then try to send those numbers to the application using  _SendMessage . I receive a reply of 0 so that tells me its all worked? however the size of my notepad hasn’t changed and isn’t restricted in any way…

      I also tried doing another read after this and the data returned is the same as the data I sent , so it looks like it’s doing something .. hmmmmm

      #include <windowsConstants.au3>
      #include <SendMessage.au3>
      
      Global Const $tagMINMAXINFO = "struct;long;long;endstruct;" & _
                                  "struct;long MaxSizeX;long MaxSizeY;endstruct;" & _
                                  "struct;long MaxPositionX;long MaxPositionY;endstruct;" & _
                                  "struct;long MinTrackSizeX;long MinTrackSizeY;endstruct;" & _
                                  "struct;long MaxTrackSizeX;long MaxTrackSizeY;endstruct;"
      
      Local $tMMI = DllStructCreate($tagMINMAXINFO)
      local $WinHandle = WinGetHandle("[CLASS:Notepad]")
      
      if @error Then
      	ConsoleWrite("Application not found " & @CRLF)
      Else
        ConsoleWrite("Application found and the handle is " & $WinHandle & @CRLF)
      endif
      
      DllStructSetData($tMMI, "MaxSizeX",50)
      DllStructSetData($tMMI, "MaxSizeY",50)
      DllStructSetData($tMMI, "MaxPositionX",10)
      DllStructsetData($tMMI, "MaxPositionY",10)
      DllStructSetData($tMMI, "MinTrackSizeX",40)
      DllStructSetData($tMMI, "MinTrackSizeY",40)
      DllStructSetData($tMMI, "MaxTrackSizeX",60)
      DllStructSetData($tMMI, "MaxTrackSizeY",60)
      
      Consolewrite("return from Send " & _SendMessage($WinHandle, $WM_GETMINMAXINFO, 0, $tMMI, 0, "wparam", "struct*") & @CRLF)

       

    • #1559714
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      Little bit of research turned up this:

      Remarks
      For a window with the WS_OVERLAPPED or WS_THICKFRAME style, the DefWindowProc function sends the WM_GETMINMAXINFO message to the window. This is done to validate the new size and position of the window and to enforce the CS_BYTEALIGNCLIENT and CS_BYTEALIGNWINDOW client styles. By not passing the WM_WINDOWPOSCHANGING message to the DefWindowProc function, an application can override these defaults.

      While this message is being processed, modifying any of the values in WINDOWPOS affects the window’s new size, position, or place in the Z order.
      An application can prevent changes to the window by setting or clearing the appropriate bits in the flags member of WINDOWPOS.

      https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanging

      David F.

    • #1559715
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Yes I read that too and though it didn’t jump out as to the way forwards I did get the message that some applications couldn’t be controlled in this way. So how to find out which ones can and which can’t or if there is a different method for ones that can’t be controlled with this method.  So I turned to notepad, it seems that no matter what you are trying tot do all the examples use notepad or calculator  to demo the function. So I thought if any app can be controlled it should be notepad. But alas not, or can it and there is something wrong with my code ?

      I’ve also been dabbling with trying to change the parent of an application to a user form but that doesn’t appear to work either. The main object of this project was to learn a bit more and I’m certainly doing that. Great if I can actually achieve the secondary objective as well but these little nudges you’re giving me David are definitely helping the learning bit..

       

    • #1559716
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Actually the set parent thing does work. What I hadn’t noticed is that notepad only appears if I move the form and thus force a redraw Note pad is then maximised to the form and restricted to within the forms boundaries. not sure if it will work with my citrix apps yet but I think I have a way forward with note pad (not that I need one with notepad :-0 )

      #include <GUIConstantsEx.au3>
      #include <WinAPISysWin.au3>
      #include <WindowsConstants.au3>
      
      ; Create a form
      global $Form1 = GUICreate("Form1", 800,800, 5,5)
      GUISetState(@SW_SHOW)
      ConsoleWrite($form1)
      ;end form create
      
      Example()
      
      
      
      While 1
      	$nMsg = GUIGetMsg()
      	Switch $nMsg
      		Case $GUI_EVENT_CLOSE
      			Exit
      
      	EndSwitch
      WEnd
      
      Func Example()
        ; Run Notepad
        Run("notepad.exe")
      
        ; Wait 10 seconds for the Notepad window to appear.
        Local $hWnd = WinWait("[CLASS:Notepad]", "", 10)
      
        ; move notpad to be within the boundary of the user form
        WinMove($hWnd, "", 7, 7, 700, 700)
      
        ; Set the parent of notepad to be the user form
        _WinAPI_SetParent($hWnd, $Form1)
      
        ; Maximise notepad to fill the form
        WinSetState($hWnd, "", @SW_MAXIMIZE)
      
      EndFunc   ;==>Example

       

    • #1559717
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      now I’ve had chance to test it with Citrix I have a new problem..

      My citrix apps are running in an invisible virtual environment called workspace. If I click shift+F2 I can see it and in it (on it) there are my apps running in citrix.

      I can’t move the workspace and set my form as its parent (not sure why it doesn’t work)  but I can make a form and make the citrix workspace its parent. So  all I need to do now is to find the handles of the citrix child processes and make my form their parent and mission accomplished. However I don’t appear to be able to get at the handles for the child processes.

    • #1559718
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      I do a *lot* of Citrix work — been my entire career, so I know exactly what you are talking about.  From a programming perspective, I have no idea what kind of games they are playing to manage it.  And you’ve already gone way beyond what I know how to do.. I’m just remembering snippets of stuff I’ve done before and been reading (and of course learning more — I want to do more with PS & AutoIT-X.

      Are you running your AutoIT inside of Citrix or outside?  My other thought was grabbing the handle as you create the processes, and then move it where you want to, and if the user moves it, just move it back and throw up a popup saying “don’t do that” 🙂  This is all assuming you are running the AutoIT and the app processes from Citrix.  So, I’d run the whole thing from inside Citrix, and have your AutoIT app be the launcher, and have it launch the child processes for your other app.

      I’m definitely interested to see how this turns out 🙂

      David F.

    • #1559719
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      I work for a big organisation and centrally served citrix. I think if I did what you say David and run the scripts on the inside then it could well do the trick but I’m not going to be given that sort of god like status anytime soon.. I’m not really knockings them as I know if they gave all us desk fellows access it would soon end up in tears.

      My next bash is to get my form to have the Citrix environment as the parent and it run another script to see if it changes the scope of what it can see.

    • #1559720
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      Well, you will probably have considerable trouble doing that, at least not without tapping the Citrix documentation.  From a general perspective, if the users are launching four copies of the application, they are going to probably be in the same session, so from the client side, you’re only going to see the first process launched, the others are likely not going to be easily visible.  I thought you were doing this from the Citrix server itself, not from the client side.

      In theory, they are all going to be wfcrun32.exe processes.   I’ll do more poking around.  I’m definitely curious.

      But, if it’s really functional, then you could talk to your Citrix admins about publishing it from the same servers, since AutoIT overhead is going to be minimal.

      David F.

    • #1559721
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      the process I’m running in Citrix is call PI Process book. If I start a couple of instances of these and list all handles,  I can see a handle for each instance. I think I had something else wrong before as I now seem to be able to set the parent for these instances to my form.  However I cant control them in terms of moving them or min/max or anything.

      I may end up trying to get AutoIt installed client side and fiddle with it there but I’m going to try and bottom it client side first if I can as this is sure to end up the path of least resistance (if it’s possible).

       

       

    • #1559722
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      I’m off for a few days and no access to the test environment.. my last tests got the applications referencing my form as parent but seemed erratically unresponsive. Thus  they would work as a display and be responsive to button clicks one minute then not the next.. This would of course not be ideal in a production environment…

    • #1559731
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      Are you calling DoEvents() in your loop?

      David F.

    • #1559732
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      good point David. Indeed I have not. A rookie mistake for sometime coming from a VBA background. I’ll stick that in next time I’m in work to see if ti fixes the non responsive occasions. Then it’s just moving and sizing the windows to fill my forms and I could be on tot something. I could probably do this whole thing from VBA within the app itself (IE I short cut a TopRight instance of the application and a BottomLeft ETC….. but as stated I wanted to use it to learn from. However if I can’t bottom the AutoIT or power shell angle I could go half way there then once I’ve moved the application’s parent to my form I could then cheat and use VBA inside the app to move it to 0,0 position and maximise it..  Problem is when I get back to work there will be a list of things I’m meant to be doing to get done and this will interfere with my fiddling.. 🙂

      avatar
    • #1559777
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Just got back to this for a few minutes and I can’t seem to find a DoEvents function in AutoIt….. I think it maybe a can’t process the event thing though as a clock on one of the displays still works but only certain buttons on it seem to accept a mouse click..

    • #1559778
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      You need the GetGuiMessage.. look up GetGuiMessage. That’s I think you what you were missing (MessageLoop Mode).

      David F.

    • #1559779
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Hello David,  unfortunately I do have a GUIGetMsg() in my loop as I’m processing the close event when I close my form and also I have a button on the form to fiddle with moving things on command (doesn’t work) but as far as I know (which isn’t very far at all 🙂 )  this is to capture the events being fired on my form to process in the loop it doesn’t have any bearing on the application responding to its own events.

      So If I set up a form then set two instances of my process book applications to use my form as their parent then they will sit on the form and be bound within it. However if the process book application has a button on it , it is hit and miss whether clicking on that button does anything. I think either the click event in the application isn’t being triggered or its being re routed somehow with the reassigning to the parent form. am I missing something here with the GUIGetMsg() ?   It does feel like I need to assign time in my loop for each application to do whatever it wants then come back to the loop.

      I’ve put a request in to the Citrix folks to see if I can slip an install of AutoIT Server side..

    • #1559780
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      Well, you can compile the script to an executable and use that for the server side.  They just need to run it once to get it extracted on the server.  (It will extract the runtime exe, any dll’s and your script).

      I’m running off of memory for the GetGUIMessage.  I remember that was part of the need to have that in your loop to make sure it doesn’t lock up the gui.  I’d definitely post it on the forums and ask.  Or switch to event driven mode, which based on what you’re describing is the route I’d be looking at.

      David F.

    • #1559781
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      I’ll have to do some more reading on the getgui message thing then…  I’m a little surprised no one else has made any comments on here, It’s only you keeping me company David 🙂

    • #1559823
      Bill Turner
      Participant
      Member Points: 511
      Rank: 2

      Making an EXE is probably the best way to deploy this. They probably would host an exe for me and give me access to the file location so I could update the exe as I see fit and run it like that. So yes this maybe a way.  I’m not getting a great deal of time to investigate this at the moment but spending a few minutes here and there.  I’ve made another break through though.   If I use the class of the citrix workspace which looks a bit like this “wMFService00010******”  rather than the actual window handle it seems to work.

      So as a recap , (all on client side)

      start the citrix application in the normal way.

      Run a script to  make a userform using the windows handle of the user form and the class of the citrix display set the parent of the display to the form.

      Move and resize the display within the form as needed.

      This now works.  So I’m one step closer. Why using the class rather than the Whnd make such a difference I’m not sure but it seems to ..

    • #1559834
      David Figueroa
      Participant
      Member Points: 5,585
      Rank: 3

      That’s awesome! 🙂 Can’t wait to see how it comes out..

      David F.

Viewing 30 reply threads
  • You must be logged in to reply to this topic.
© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account