Forum Replies Created
-
AuthorPosts
-
thomb@bossoft.com
ModeratorI concur with the above – to give some more details on what is being describe above re location of the text if someone wants to go down a very deep rabbithole. The effect being described is called sub pixel rendering. Typically this is a left to right change thing.
What I recommend is standardizing screen size and position – see ActivatePosition
Activate Commands (bostonsoftwaresystems.com) Which really is a good thing in general because of convenience!
Even working with terminal emulators and stream connections I set screen size/position so that my development tools and the application land where I want them to help me toggle between one or the other. You’d be shocked how simple things like that improve productivity!
June 20, 2023 at 8:33 pm in reply to: RE:sending emails from an automation and also detect within runtime environment #4943thomb@bossoft.com
ModeratorNICE!!!
thomb@bossoft.com
ModeratorHi Mehdi,
I thought I could look up your account to reach out but alas I cannot. If you need help, please reach out to Support@bossoft.com and we'll work with you on this.
Regards,
Thomthomb@bossoft.com
ModeratorThe connection works well with Expanse.
I'll be reaching out directly btw.
However for the group.The most likely cause when this (or a rule/pause/at not working) is that there is text from a prior window also there – and it confuses the command. Its a long story why that can occur ( the documentation section Meditech Client Server Overview) covers how their screens "work)
The solution is to clear and refresh the screen.
This is the command that clears:
Connection.Windows.Clear
Then to refresh it, you <do something> that causes Meditech to resend all of its text.
Most of the time, you can do that by using:
Key "{F5}"
thomb@bossoft.com
ModeratorThe problem is that keys like that are "hits" whereas when a user does those sequences, the are really press, press, release, release. The reason that may work "intermittantly is due to app response time.
Here's how to more closely mimic how a user presses and releases keys:
Sub SelectWithKeys()
Dim k As New BWS10.Keys
' Be sure you are in the field first with a Pause etc -these keys just send they make no attempt to activate a window etc!!
k.Press "{SHIFT}", SendInput_
DoEvents_ ' these are important to mimic user speed – may even need more than one…
k.Press "{CTRL}", SendInput_
DoEvents_
k.Press "{CTRL}", SendInput_
DoEvents_
k.Press "{END}", SendInput_
DoEvents_
k.Release "{END}", SendInput_
DoEvents_
k.Release "{CTRL}", SendInput_
DoEvents_
k.Release "{SHIFT}", SendInput_
k.Key "{BS}", SendInput_
End Subthomb@bossoft.com
ModeratorHum… not aware of there being a limit…(I'll check).j
Just out of curiousity, try using a ; – semi colon for the delimiter.thomb@bossoft.com
ModeratorNow the question I have is, do you need to determine radio button state and conditionally click it? or just click the one you want?
To click the 1st, 2nd or 3rd radio button – those are just larger offsets (or even offsets from different text) a distiction really without a difference 🙂If you need to determine state…or if anyone else is interested in that, post here and I'll write up how to do that.
thomb@bossoft.com
ModeratorHere is the registration link for today.
https://attendee.gotowebinar.com/register/4999216978641953281thomb@bossoft.com
ModeratorUGH… I have a mental block on that evidently – its fixed now.
thomb@bossoft.com
ModeratorAnother thing to check based on feedback:
Open an instance of BWS – under Options – look at Fix for Timers – check to see that it is enabled (its a toggle icon). If it is NOT enabled (toggled on) – toggle it on and close BWS. Open BWS again and verify Fix for Timers is set.thomb@bossoft.com
ModeratorI know that support has reached out to some folks here on this. There's all sorts of, likely highly specific, things that could cause something like this.
One thing I do see here:
performance is set for background serviceI've seen poor performance of the desktop in general and our software in particular when performance is set for background services.
As with anything like this, its never a black and white thing – e.g. Set to Background =bad everywhere… but its not a recommended setting, and I've seen changing it to Programs solving problems.
thomb@bossoft.com
ModeratorDoes that happen manually? It looks more like a "functional type problem " than some sort of technical incompatability?
The black B is the MeditechFocus.exe's user interface, its showing what you'd see inside Boston WorkStation if you selected Connect -> Stream menu and used Meditech as the stream name. It also has some specific troubleshooting oriented UI's.thomb@bossoft.com
ModeratorJust as an informational post. There are pre-built methods for evaluating cursor positions:
Pause "@10,20" 'Where Row=10 and Col=20 – this will continuously check until that's where the cursor is
At ("@10,20") – a boolean check – is the cursor there or not.These support all sorts of nice constructs for defining ranges as well, or wildcarding, and even comparing text near the cursor.
Evaluating Row and Col properties directly is useful for reading "near" the current cursor postion (the View command does support 0 to indicate current row/current column – but I prefer the readability of using Row or Col instead)
Rows and Cols return the number of rows or columns a given stream connection is supporting. Typically these properties are useful when reading dynamically using a For/Next – Rows being the most useful
For i=1 to Rows – read down all the rows
Cols would tell you the length of rows if the use case was read an entire row for some reason.thomb@bossoft.com
ModeratorHere's how that connection works:
When MeditechFocus_V2.exe starts it continuously looks for any instance of Meditech C/S and when it sees one (as the foreground window) it will under the covers do Connect ..stWindows -and set up a bunch of stuff to allow it to report the text and cursor position).Then anything can use Connect "Meditech", stStream
Anything being – the BWS UI, or a C# a program referencing BostonWorkStation70.dll, etc.) and see whatever MeditechFocus_V2 is "seeing".MeditechFocus_V2.exe also has its own UI that shows what its seeing. (the systray black B icon).
So what we need to know is, what is MeditechFocus.exe seeing.
Your original post suggested it was seeing what you were expecting? (BWS UI) – now of course since its a different rev of Meditec, it could be connecting just fine, but your C# program is expecting different text or cursor positions.Probably best to sort this out by calling Support!
thomb@bossoft.com
ModeratorYou don't want to know how many times I've declared the variable:
Dim sTop as Long
Why that errors out stumps me for minutes every time and gives me a good laugh at my own expense afterwards!
thomb@bossoft.com
ModeratorYou're gonna kick yourself 😉 you're using DateDiff as the sub routine name.
So its erroring out because you've created a recursive routine -but you're passing parameters to DateDiff when you try to call datediff 🙂Change the sub routine name and you're good to go
thomb@bossoft.com
ModeratorUnfortunately, there isn't a property that can give you the current sub routine name
This means, as has been suggested, you're going to need to set the routine name somewhere. One thing I like to do, inside any "useful" sub routine I add: Note="nameGoesHere"
This way if you are logging Notes, then you'll see the note in the log – which helps you know that routine was called, etc.
thomb@bossoft.com
ModeratorAs an aside…which perhaps I should have suggested at first 🙂
You can <make> a .BWS file have the same user experience as a .EXE – e.g. run as a shortcut, not have any visible BWS stuff, display forms etc. .BWS files have the benefit of being more flexible to different versions of BWS. Worst case, you may have to change the reference in VBA (if your development machine is a newer version of BWS than what is installed on the client's machine).
thomb@bossoft.com
ModeratorThat sounds like there are different versions of BWS installed on your machine and theirs – the downside of references/early binding
This is complete info for the "record" if you will…
If you can't change the version on the clients machine then you'll need to switch to late binding – uncheck the reference to BostonWorkStation70 Main Dll.
Then add
Public B As Object
…
Set B=CreateObject("BostonWorkStation70.BostonWorkStation")and prefix all BWS commands with B.
Or… it could be a control you're using in the EXE completely seperate of BWS and its version is different (probably unlikely but it is possible).
To rule this in/out create a simple project w/ form and all used controls added – run that exe there.thomb@bossoft.com
ModeratorLooks like a dynamic loading menu. Perhaps there's a MouseOver event happening somewhere to cause the loading? I am pretty sure this can be sped up dramatically. Support will be happy to help out here. But not seeing it, where I'd start is looking at that first element you click – is there an onmouseover (Web1.Selected.onMouseOver)
​Look for the same thing on the Select – or perhaps the parent of the select (wrapping a select with a Div is a common way to implement a dynamic menu)thomb@bossoft.com
ModeratorI will gladly entertain requests on topics and how to improve!
thomb@bossoft.com
ModeratorThe Variable display is a static view – helps with learning, so when you build Enter someSelectedVariable it has some data to type. This isn't what F(someSelectedVariable) would have in runtime.
The Flags view is the "what does this equal now" in runtime. That's why you see one view clear but not the other.
thomb@bossoft.com
ModeratorYes
Dim B as New BostonWorkStation
B.command
…
I'd MUCH rather see some Pause commands verifying what's going on in there though – it look like you're repeatedly clicking the same spot several times – does something change on the screen when you do that? Pause commands for images showing the change will makes sure the changes actually occured.thomb@bossoft.com
ModeratorThere are some videos in the webinar archive that will help get you going. Just remember that your commands will eventually need to use the declared BostonWorkStation object I described earlier. I can't stress enough building and testing everything you do with OCR seperately until you have it perfect. That'll make the assembly pretty painless. We've handled these screens what that approach before and it works very well.
If you get stuck along the way, don't hesitate to call Support!
thomb@bossoft.com
ModeratorThis a newly created or newly used for web connection machine?
​That's almost looking like Processor Scheduling being set to favor background processes vs applications – I've seen that cause odd problems with web – especially something like this. Worth taking a look. System Properties -> Advanced -> Performance pane click Setting -> Performance Options select Advanced tab.thomb@bossoft.com
ModeratorAh… that is by design. The document list, as you've likely seen when developing, is resource intensive to build. This means during runtime it will not update at all – but commands will work successfully.
​Manually clicking the list is how you get the elements to display to allow building further commands.
​
​Hope this helps!
​Thom
thomb@bossoft.com
ModeratorDo you get any ? (question marks) in the variable that is supposed to be storing the read data.
​Seeing question marks means the View is indeed seeing letters that could be recognized – but were not because there was no match in the font file (or perhaps a font file not loaded at all). So question marks = a font file related issue.​If you see !, then that means there wasn't any letters seen by the View. A ! indicates the font file isn't your problem at all, but instead you have a problem with readiness – you are performing a view when there isn't letters there to view.
thomb@bossoft.com
ModeratorHi Kevin, telnetserver.exe in the BSS70 directory acts as a simple host system. Its job is to display escape characters being sent by an emulation. I been successful using it to solve these types of problems. In the BWS Help, search for TelnetServer – this is help topic you're looking for:
Determining Escape Sequences and Key Mappings
I'm happy to take a look at it Monday if needed.thomb@bossoft.com
ModeratorWhat you had above is close, – you don't need to do Set Web1.Selected = Web1.Selected.children.Item(x)
Just do
Dim ListItem
For i =0 to web1.Selected.Children.length
set ListItem=Web1.Selected.Children.item(i)
'now listItem is the Li – do whatever
Next ithomb@bossoft.com
ModeratorAh its a UL / LI construct – the A tag is likely not the one that will control the mouseover then – its being altered by something else.
What you want is a parent of the A – perhaps the LI or a parent of it – the UL. Or perhaps even some DIV tag further up the parent chain – try doing fireevent onmouseover's on those..
thomb@bossoft.com
ModeratorOn a 64 bit OS, c:WindowsSysWow64
On a 32 bit OS, c:WindowsSystem32thomb@bossoft.com
ModeratorAlso heard from someone who emailed me directly. It may be possible to do what you need to without accessing the viewer at all? What if you right click on the link do you get a Save as option? If so that could be replicated.
thomb@bossoft.com
ModeratorAh, forgot to add… The Run dialog needs to be run as an administrator.
And if someone can tell me how to do that easily on Windows 10 I will be eternally greatful!thomb@bossoft.com
ModeratorThe best way to do that is to put the code into a sub routine. Build a rule that detects when to call the routine, edit the actions for the rule and call the routine.​If the routine was called "SelectLine" then your rule's Action would be:SelectLinethomb@bossoft.com
ModeratorFont reading issues over Citrix are caused by 2 things.
1. Not having learned the font(s)
2. Clear Type being on which causes "fuzzy fonts" – easiest way to handle this is to search for Clear Type on the running pc and turn it off. (will make letters look kinda funny – but thats a good thing).Support is happy to help here.
thomb@bossoft.com
ModeratorI am wondering if the bar is just not fully "operational" when you first detect it? I know it pulses from yellow to orange for a user; with orange indicating full readiness.
You could try the existing logic with a check for success – if it didn't get to the resulting dialog, retry.thomb@bossoft.com
ModeratorThe issue you likely were having is that the button's HTML changes when your mouse is over it.
It goes from having a classname of btnMouseOver to simply btn when the mouse isn't over it. Using the mouse hover trick is going to get the mouse over variation. When you run / try that command, since the mouse isn't over it, that element no longer exists, the command fails.
Your command excludes the part of the findstring that was detecting these changes. Since you filled in email address and password, the button is the next Input element on the page, so that findstring is perfectly valid.
December 15, 2015 at 10:14 pm in reply to: RE:Win 7, MeditechNUI Connection and Task Scheduler #4733thomb@bossoft.com
ModeratorQuestion, when you are running from Task Scheduler, is this a PC you are accessing via Remote Desktop?
thomb@bossoft.com
ModeratorExactly – that in a .BAT file will disconnect you from the RDP session, moving the session to the console allowing it to stay interactive.
thomb@bossoft.com
ModeratorNot sure I understand about "disconnect the screen" via code? The PC needs to be exactly as if a user was on the PC. If this is a true standalone piece of hardware, then you could physically disconnect the monitor – the hardware isn't necessary.
thomb@bossoft.com
ModeratorDropdowns can either be quite simple:
Click "text of the option<OPTION>@title etc."
or there can be all sorts of complexities – all depends on who built the site. If the above suggestion doesn't work – call into support.thomb@bossoft.com
ModeratorI don't see a connect command after your Activate?
You'll need
Connect "CMS Provider Portal",stWeb1
Also
Text("<INPUT>#ctl00_MainContent_txtNPINumber#<#text-input#>@CMS Provider Portal") = ("")
the ("") is what's causing your error
remove the ( ).thomb@bossoft.com
ModeratorScratch assumption #1 – that's irrelavant 🙂 The code I sent would work against many windows popups as well.
thomb@bossoft.com
ModeratorHi Ryan, since there's alot of variables here – I wouldn't know exactly how to direct you. I'd give Support a call here. I'm going to pass this message along so they know to expect your call.
Just out of curiousity, any reason why you aren't using HBOWem for STAR?
thomb@bossoft.com
ModeratorExcellent! Glad to see that option #1 was the way you're able to go!
thomb@bossoft.com
ModeratorGotcha,
I've had good success with fixed length and things like you describe. One thing to keep in mind is, your fixed lengths always get parsed for a given line in the file. You can use that to your advantage by doing pattern matching on the fields. This allows creating fields that parse the upper (or lower) parts of the report, and then the comments section. If they exist in the report, include field lables in the parsed fields so you can do things like:
If d("field…") like "Account:*" then you know you have parsed the Account field.
You can do the same thing to find when your comments fields start and end:
If d("field…") like "*Comments*" then NextRowWillHaveComments=True….
That sort of thing.Good luck I envy you having this project!
I've always liked data parsing for some reason – call me strange 🙂thomb@bossoft.com
ModeratorBWS supports a command line approach to starting up an automation.
You can build the command line by using the Create a Shortcut feature. Do like you do today to run Main. But instead of running it, select Options -> Create a shortcut – follow the prompts.The proprties of shortcut on the desktop has what you need to run Main – or you could simply use that shortcut too.
Another alternative is to use the BWS scheduler – making sure BWS is constantly running w/ that project open.
March 6, 2015 at 11:02 pm in reply to: RE:Can select item in drop-down list, but page will not update #4889thomb@bossoft.com
ModeratorSounds like this one is going to be a bit recalcitrant as they say.
Here are some other things I've tried before, if none of these work, give us a ring it's hard to try stuff without trying stuff :
- Typing the whole text w/ sendkeys followed by tab after you've set focus
- Use sendkeys with {DOWN} – read Web1.Selected.ParentElement.Value (maybe?? I forget exactly) – check Web1.Selected.ParentElement.OuterHtml – that will show how it's storing what is the selected.
- Maybe a simple sendkeys up/down
- Web1.Selected.Parent.FireEvent("OnChange")
thomb@bossoft.com
ModeratorAnother trick to add when looking at web elements.
In some elements, web1.outerhtml has things like Data-target-url=”stuff” style=”stuff” etc.
You can get access to “Stuff” by the words before the equal sign.
For example, I had a nasty navigational element that just was being recalcitrant.
But thanksfully there was an attribute called data-target-url which I could use to trigger the nav simply and reliably by doing:
Web1.Go_ (web1.selected.GetAttribute(“data-target-url”)thomb@bossoft.com
ModeratorGlad to hear that!
Thanks for replying.thomb@bossoft.com
ModeratorThe OCR connection isn't compatible with Rules for a variaty of reasons.
But you don't need to manually type the code.
Under the Commands menu, toggle either Record at Cursor (to put the commands at a spot) or Record in MyScript to have BWS create a sub routine for you.
thomb@bossoft.com
ModeratorThe OCR dialog does not have logic to detect the current running screen titles like the windows connection (that is feature I will get added in a future release). So type the title in.
thomb@bossoft.com
ModeratorMany elements on a web page can be thought of as a container. Some are obvious, like a TABLE contains any number of TR elements (rows), and each TR could contain any number of TD (cells) elements. Dropdowns (SELECT) have OPTION elements; but even formatting elements also can be thought of as a container, for example a a B tag (bold) could format a A (hyperlink) element.
Containers have a general method for accessing their members, and for some container specific methods. A TABLE for example can be read easily using our Web1.Table command. If lower level access to the individual items inside a table you can access the Rows collection,and each Rows.Item has a Cells collection:For i=0 to Web1.Selected.Rows.Length-1Web1.Selected.Rows.Item(i).Cells.item(0)Next iA SELECT tag has an Options collection – all the available items inside the combo box.All containers have an All collection – everything inside the container. For example let’s imagine the first cell from above had a hyperlink inside it that you wanted to click. The link could be the 1st item inside the cell’s All collection:Web1.Selected.Rows.Item(i).Cells.item(0).All.Item(0).ClickNow, before you go writing stuff like the above – make sure you really need to!I may have been able to click the hyperlink above with a simple, learned web command – Click “My Link Text<A>”. Don’t fall into the trap of having a hammer and now you treat all problems as nails.thomb@bossoft.com
ModeratorI purposefully left a bit of a cliffhanger there. Our web command search using what we call a FindString. A FindString uses: elements inner text, tagname, ID if it has one, classname if it has one and document title(s) – multiple if the element is within a framed site. Any combination of items can be removed from a find string, and each portion supports wildcards as well. Of course, there can be more than one element with all of the combinations being the same – a link that says Download on a page with multiple Download links. But also the nesting of elements matters. A Table element for example, its innertext contains all of the text within the table, any subsequent tables contained within cells inside the table and on and on. This is why the concept of moving down the list from the last place is so key. You can re-search using the exact same FindString and get the next thing that matchs. Or you can search for something different from the last point to drill further into something.
thomb@bossoft.com
ModeratorUnderstanding the traversal process is a fundamental skill in web automation. The BWS web commands greatly simplify the task by searching the list for you from the last place it found something. The reason why this approach is so necessary is that not everything on a webpage has a unique identifier. Well I should rephrase that, web programmers and the tools they use allow uniquely identifying elements, but do not require it. Your thought process often needs to be “the thing I want to read is the first (or second or) element of a particular kind after this thing that I can uniquely identify.Note: being able to uniquely identify an element does not necessarily mean that the web developer assigned it a unique ID.thomb@bossoft.com
ModeratorDirect element find is the simplest to understand – the element you need to read can be found using a basic command.f("MyData)"=Text(findString)Direct element find in practice though is most often used in conjunction with the other two strategies, because it sets the current selected element: Web1.SelectedAllowing for either traversal down the list from that point using:
Set Web1.Selected = Web1.NextElement(Web1.Selected)
Or another Pause command:
Pause "a very specific find string"
Pause " a not so specific find string"
f("MyData)"= Web1.SelectedOr integrating a container located by a direct find e.g.
Pause “<TABLE>#GotLuckyTableHasAnID#”F("MyData")=Web1.Table(2,2) ' give me text from row 2, column 2
thomb@bossoft.com
ModeratorHow do you deal with the situation of a given element having something else load afterwards? Easy, use a Pause command for an element that loads after that.
The programmer or absolute answer seeker type may wish to explore the concept of absolutely knowing the page has loaded.
I caution you about this approach for 3 reasons:
1. You will apply it to every page transition in every automation you write, needlessly slowing them all down.
2. You may think you have solved knowing when pages are loaded. Trust me on this one, you will never fully understand how progressive loading really works in all situations.
3. Because your understanding is by definition incomplete, you will never actually get this universally page load detection right – but you think you have because it will work in many situations; giving a false sense of security.
thomb@bossoft.com
ModeratorThe savvy reader noticed a distinct lack of absolute in that last statement. The only absolute in automation is that there are no absolutes as Heraclitus would say.
Some theory is in order. We see a website by interacting with its document object model – a complex hierarchical set of objects that represent everything. We greatly simplify this complexity by flattening the hierarchy in various ways into a simple list; the web commands search the list in various ways.
As you have no doubt experienced, websites load progressively – keeping you from getting frustrated since you can begin interacting with content as the rest loads. Our commands can do the exact same thing. For most situations, this behavior is a very good thing, it’s fast and also reliable.
However, most situations are not all situations. Rarely, a given website may have a given element that will progressively load first, but something else (typically some sort of client side code) progressively loads or executes.
Please carefully read and understand what I just wrote. This is situational – element A on page C of website X has this behavior.
thomb@bossoft.com
ModeratorSomeone may ask hey where are the Pause commands? What knows that the page has loaded? That is the beauty of the basic commands – they ARE a Pause command. In fact, Click "Customer Center Login<A>#ctl00_lnkLogin#"
Is actually doing:
Pause "Customer Center Login<A>#ctl00_lnkLogin#"
Web1.Selected.ClickThe Text command does the same thing. This means for most situations, you do not need to care about the loading state of the entire page etc.
thomb@bossoft.com
ModeratorUse Enter "Quit" to get out of the sFTP application
Then use Connect "",stStream to close the Console window
thomb@bossoft.com
ModeratorWhat connection are you using to type into the Console?
thomb@bossoft.com
ModeratorOk I can see what is happening. Formatting dates where the datatype is string is tricky (and as you saw also dependant on the PC).
For examplerd = "101214"Debug.Print Format(rd, "mm/dd/yyyy")This is the result: 02/09/2177
If you are capturing input from a user, it's likely they could use different date formats. A generic formatter to convert them all will be a challange.I'd be inclined to use a VBA userform with a Microsoft Date and Time Picker control. Here's an example:
/site/Customers/Boston-Workstation/Script-Center/Utilities/USer-Forms/Date-Selection-Dialogthomb@bossoft.com
Moderator
Wow, learn something new everyday! Never knew about the mouse click "keystrokes". Well done and thank you!.thomb@bossoft.com
ModeratorI am a treble seller – I mean terrible speller.
A feature a knew I needed in my post editor was spell check. Why? Well
A. Because I wanted to see if I could
B. I knew I’d be editing posts to fill in details.
It turned out I spent too much time on the spell check – mostly because instead of simply figuring it out, I used some else’s buggy code I found on the internets. BIG mistake – ended up learning how it works anyway 🙂
The attached text file is my spell check code. Note this requires a reference to MS Word:thomb@bossoft.com
ModeratorA word about the above. I don’t use arrays all that often except as the result of a Split – which I use ALOT.
The only reason I used a second array was so I could use Join to create a string from it.
I learned though that to add an item to an array, you have to create a place for the new item.
To do this you use the ReDim Preserve command, here is the code I used:
ReDim Preserve tc(k)
tc(k) = t(i)
Yeah I like small variable names 🙂 TC is the array, K is a counter, t is the array created by the split command. The short names make sense to me, and I am the only one ever to read this code 🙂 -
AuthorPosts