Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I want to display the battery popup when the user clicks on the tray icon of my application.
I searched around for quite a while but I couldn't find any API for this, neither .NET nor native. Is this possible (e.g. via P/Invoke)? I am using WinForms, but that shouldn't be relevant.
I am speaking of these windows:
You can use Windows UI Automation as explained here: Enumerating notification icons via UI Automation
The difficulty is to find the power icon, whatever the end-user language is. Luckily, some icons have an AutomationId set, so we can search the power one using its id.
There is one issue though: for some reason the UI automation dlls (UIAutomationXXX) shipped with Windows are not up to date (and buggy) so don't use them for this task, and use the UIAComWrapper dll (originally written by a Microsoft guy) instead, for example from here: https://www.nuget.org/packages/UIAComWrapper/
So, here is a sample Console app code (with helper code from the link above):
static void Main(string[] args)
{
// you can find the value of this guid using SDK's "inspect" tool, hovering over the power icon.
var SCAID_Power = new Guid("7820ae75-23e3-4229-82c1-e41cb67d5b9c");
var power = EnumNotificationIcons().FirstOrDefault(i => string.Compare(i.Current.AutomationId, SCAID_Power.ToString("B"), StringComparison.OrdinalIgnoreCase) == 0);
if (power != null)
{
power.InvokeButton();
}
}
public static IEnumerable<AutomationElement> EnumNotificationIcons()
{
var userArea = AutomationElement.RootElement.Find("User Promoted Notification Area");
if (userArea != null)
{
foreach (var button in userArea.EnumChildButtons())
{
yield return button;
}
foreach (var button in userArea.GetTopLevelElement().Find("System Promoted Notification Area").EnumChildButtons())
{
yield return button;
}
}
var chevron = AutomationElement.RootElement.Find("Notification Chevron");
if (chevron != null && chevron.InvokeButton())
{
foreach (var button in AutomationElement.RootElement.Find("Overflow Notification Area").EnumChildButtons())
{
yield return button;
}
}
}
public static class AutomationHelpers
{
public static AutomationElement Find(this AutomationElement root, string name) => root.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, name));
public static IEnumerable<AutomationElement> EnumChildButtons(this AutomationElement parent) => parent == null ? Enumerable.Empty<AutomationElement>() : parent.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button)).Cast<AutomationElement>();
static public AutomationElement GetTopLevelElement(this AutomationElement element)
{
AutomationElement parent;
while ((parent = TreeWalker.ControlViewWalker.GetParent(element)) != AutomationElement.RootElement)
{
element = parent;
}
return element;
}
public static bool InvokeButton(this AutomationElement button)
{
var invokePattern = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
invokePattern?.Invoke();
return invokePattern != null;
}
}
Your app should be able to use the same information that the OS uses to display the battery stats. This doesn't mean you should use the same UI as the OS. I don't suppose you can access that programmatically. And if you did, how would you be able to plug it into your application?...
Try querying WMI to get the data you want. Perhaps class Win32_Battery is what you need.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I'm creating a unity quiz game using input fields.
How can I use text from an input field to match with an answer in a c# script?
hijinxbassist's example is good, however, i made an example that includes the other parts as well, like adding event listeners and declaring the fields.
Checking for single correct answer:
public Button submitAnswerBtn; // assign a UI button object in editor
public InputField answerInput; // assign a UI inputfield object in editor
private string a1_right_answer = "foo"; // make it public and edit the answer in editor if you like
private void Awake()
{
// add event listener when button for submitting answer is clicked
submitAnswerBtn.onClick.AddListener(() => {
// validate the answer
if(answerInput.text.ToLower() == a1_right_answer) {
// success
Debug.Log("Correct");
} else {
Debug.Error("Wrong");
}
});
Checking for multiple correct answers:
public Button submitAnswerBtn; // assign a UI button object in editor
public InputField answerInput; // assign a UI inputfield object in editor
private string[] a1_right_answers = { "foo", "bar", "foo1", "bar1" }; // multiple right answers
private bool is_right_answer = false; // default value
private void Awake()
{
// add event listener when button for submitting answer is clicked
submitAnswerBtn.onClick.AddListener(() => {
// loop through all the right answers
for (int i = 0; i < a1_right_answers.Length; i++)
{
// validate the answer
if(answerInput.text.ToLower() == a1_right_answers[i]) {
// success
is_right_answer = true;
break;
}
}
// check if the user got the right or wrong answer
if(is_right_answer) {
Debug.Log("Correct");
is_right_answer = false; // reset for next guess
}
else {
Debug.Log("Wrong");
// no need to reset 'is_right_answer' since its value is already default
}
});
I am not sure which part of this problem you are stuck on, but I will attempt to answer.
I think the most important thing when comparing an input field with a stored answer is to make sure the comparison is case insensitive. You can do this by converting both texts to either lowercase or uppercase.
var usersAnswer = answerInputField.text.ToLower();
var actualAnswer = "Some Answer".ToLower();
if (usersAnswer == actualAnswer)
{
Debug.Log("You got it right!");
}
I'm trying to automate a windows based application Using Coded UI. In this application some control are not accesible so i have used UI automatin element to identify the control.
First Screen Contains List of Employees in the form Grid.
When user Doubles click on selected Employee. New Tab is created where it contains emplyee Details in the form of TextBox
New TabPage we have TextBox and some other controls such as Checkbox and ListItem.
List Item are detectable using coded ui but TextBox are not detectable with coded ui so we have used UI Automation Element for this.
[CodedUITest]
public class CodedUITest1
{
[TestMethod]
public void CodedUITestMethod2()
{
LaunchApplication(); //done using coded ui
Login()//done using Coded UI;
ClickonEmpListTab()//Done Using Coded UI
SelectEmployee()//done using Coded UI
//now new Tab is created in application
empoyeeUICodedUIControl.CurrentEmpComboBox.Checked= true; //done using coded ui
empoyeeUIAutomationControl.EnterText(empoyeeUIAutomationControl.FirsName,"MyFirstName"); // done using coded ui
empoyeeUIAutomationControl.EnterText(empoyeeUIAutomationControl.LastName,"MyLastName"); // done usin coded ui
}
private EmployeeUIAutomationUIMap _employeeUIAutomationcontrol;
public EmployeeUIAutomationUIMap empoyeeUIAutomationControl
{
get
{
if(_employeeUIAutomationcontrol == null)
{
_employeeUIAutomationcontrol = new EmployeeUIAutomationUIMap();
}
return _employeeUIAutomationcontrol;
}
}
private EmployeeUIMap _employeeUICodedUIcontrol;
public EmployeeUIMap empoyeeUICodedUIControl
{
get
{
if (_employeeUICodedUIcontrol == null)
{
_employeeUICodedUIcontrol = new EmployeeUIAutomationUIMap();
}
return _employeeUICodedUIcontrol;
}
}
// Class contains controls which are detectable using coded ui
public class EmployeeUIMap
{
public WinTabPage ListEmpmTab
{
get
{
WinTabPage tab = new WinTabPage();
return tab;
}
}
public WinCheckBox CurrentEmpComboBox
{
get
{
WinCheckBox combox = new WinCheckBox();
return combox;
}
}
}
//Class contains Control which are detectable using UI Automation Element
public class EmployeeUIAutomationUIMap
{
public Condition GetCondition(AutomationProperty propery,string value)
{
Condition cond = new PropertyCondition(AutomationElement.AutomationIdProperty, value);
return cond;
}
public AutomationElement GetElement(AutomationElement parentControl,Condition cond)
{
return parentControl.FindFirst(TreeScope.Descendants, cond);
}
public AutomationElement MainRootElement
{
get
{
return AutomationElement.RootElement;
}
}
public AutomationPattern GetPattern(AutomationElement element)
{
//returns the pattern as per element
return pattern;
}
public void EnterText(AutomationElement element,string value)
{
var pattern = GetPattern(element);
pattern.SetValue = value;
}
public AutomationElement FirsName
{
var cond=GetCondition(AutomationElement.AutomationIdProperty,"FNID");
var element=GetElement(MainRootElement,cond);
return element;
}
public AutomationElement LastName
{
var cond=GetCondition(AutomationElement.AutomationIdProperty,"LNID");
var element=GetElement(MainRootElement,cond);
return element;
}
}
When i Run my TestMethod it works fine till clicking on selected employee. once new tab page is opened i perform operation on checkBox using coded ui which workds, but when i try to enter text in textbox using UI automation. It throws null exception in GetElement() Method on element.
So i commented below code and manually opened the application till new tab is opened. and run the test method, now uiAuomation recognizes the element and perform the respective action.
[TestMethod]
public void CodedUITestMethod2()
{
/*
LaunchApplication(); //done using coded ui
Login()//done using Coded UI;
ClickonEmpListTab()//Done Using Coded UI
SelectEmployee()//done using Coded UI
*/
empoyeeUICodedUIControl.CurrentEmpComboBox.Checked= true; //done using coded ui
empoyeeUIAutomationControl.EnterText(empoyeeUIAutomationControl.FirsName,"MyFirstName"); // done using UIAutomation element
empoyeeUIAutomationControl.EnterText(empoyeeUIAutomationControl.LastName,"MyLastName"); // done usin Automation Element
}
When i run my complete test method UIAutomation is not able to identify the control.
Please help me to resolve the problem.
UI Automation is a framework to implement standardized support for non-standard UI widgets. This being said, if the support is not implemented(and installed) on the test machÃne, CUIT will handle all objects as generic Objects. You need to implement support first via the UI Automation framework for your widgets aka you have to teach windows why a specific WinClass is a Button and what should happen in the background when it is clicked.
Afterwards CUIT will be able to interact with your Object. So don't think of UI Automation as a magic solution for everything. It is something similar like the HPE UFT Extensibility Kit, just on a lower level (OS). HPE Ext Kit operates on the Application Level
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I am developing a project in C#, for which I want to login/authenticate a user using their fingerprint.
I bought a ZK4500 Fingerprint scanner and got its SDK from http://www.zkteco.com/product/ZK4500_238.html. The SDK is in C++.
So How can I integrate this SDK with my C# project to perform the desired functionality?
You need to add reference to ZKFPEngXControl that will appear under COM Type Libraries. After that you can use the ZKFPEngX Class to do whatever you require.
using ZKFPEngXControl;
and then
ZKFPEngX fp = new ZKFPEngX();
fp.SensorIndex = 0;
fp.InitEngine(); // Do validation as well as it returns an integer (0 for success, else error code 1-3)
//subscribe to event for getting when user places his/her finger
fp.OnImageReceived += new IZKFPEngXEvents_OnImageReceivedEventHandler(fp_OnImageReceived);
You can write your own method fp_OnImageReceived to handle the event. for example you can write this in that method;
object imgdata = new object();
bool b = fp.GetFingerImage(ref imgdata);
Where imgdata is an array of bytes.You can also use other methods in ZKFPEngX, to achieve your goals. Remember to close the engine when form closes.
fp.EndEngine();
You can store a fingerprint under OnEnroll(bool ActionResult, object ATemplate) Event.This event will be called when BeginEnroll() has been executed.
//Add an event handler on OnEnroll Event
ZKFPEngX x = new ZKFPEngX();
x.OnEnroll += X_OnEnroll;
private void X_OnEnroll(bool ActionResult, object ATemplate)
{
if (ActionResult)
{
if (x.LastQuality >= 80) //to ensure the fingerprint quality
{
string regTemplate = x.GetTemplateAsStringEx("9");
File.WriteAllText(Application.StartupPath + "\\fingerprint.txt", regTemplate);
}
else
{
//Quality is too low
}
}
else
{
//Register Failed
}
}
You can try to verify the fingerprints under OnCapture(bool ActionResult, object ATemplate)event. This event will be called when a finger is put on the scanner.
Add an event handler on OnCapture Event:
x.OnCapture += X_OnCapture;
Verify the fingerprints when the event has been called (a finger is put on the scanner):
private void X_OnCapture(bool ActionResult, object ATemplate)
{
if (ActionResult) //if fingerprint is captured successfully
{
bool ARegFeatureChanged = true;
string regTemplate = File.ReadAllText(Application.StartupPath + "\\fingerprint.txt");
string verTemplate = x.GetTemplateAsString();
bool result = x.VerFingerFromStr(regTemplate , verTemplate, false, ARegFeatureChanged);
if (result)
{
//matched
}
else
{
//not matched
}
}
else
{
//failed to capture a valid fingerprint
}
}
I work at a place that blocks social media sites and pops up a proxy log-in for those (few) folks who have legitimate business reasons for going to them. Since most sites have a Facebook, Twitter or similar link, the proxy prompt comes up quite a bit. When browsing in a normal, human-driven fashion, I just hit the ESC key to get rid of the proxy log-in dialogue. How can I do this via Selenium? I've seen alot of posts and solutions for either closing ALERT messages or modal dialogues but I haven't seen anything for closing the proxy log-in; just bypassing it by supplying credentials.
Any help/tips would be appreciated. Thanks!
Specs:
I'm using Selenium 2.44 with the Firefox driver in C#
(Edit #2: A little more info on this dialogue)
This log-in prompt is coming from our own internal proxy server. Our proxy server is basically asking the user if they even have permission to go to the site requested before any communication is made to the remote site. It pops up any time an element is on the remote site. So for instance, if a site has a button for Facebook and Twitter which pulls the button from Facebook or Twitter itself, the user will see two proxy log-in prompts. While the other elements of the page will load as it waits, the page-load process ultimately waits for an answer for any elements that are otherwise automatically blocked.
One way I have gotten around this is to use the Firefox driver in combination with NoScript and remove all social networking links from the white-list. It's a crude workaround and forces the use of one browser. What I'm seeking is a way for Selenium to simply close the proxy log-in prompt via code (if that even be done).
(Edit: Added screenshot example)
(Edit: Added screenshot from Inspect)
Not sure about selenium but you could use the System.Windows.Automation namespace instead.
Subscribe to top level window opens
Use the AutomationElement received to check if it matches your Firefox window information (you can use a took like Inspect to find out what they are)
Use the AutomationElement above to subscribe to child window opened events
On event, check if it is the proxy popup
Use the close method on it or SendKeys to send an ESC
Here's a sample code, you will have to gather the classnames, automation ids and names of the windows (feel free to commend and I'll edit the answer):
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Automation;
namespace FirefoxAutomation
{
class FirefoxAutomation
{
private const string FF_CLASSNAME = "MozillaWindowClass"; //"Firefox ClassName taken from Inspect";
private const string FF_AUTOMATIONID = null;//"Firefox AutomationId taken from Inspect";
private static readonly Regex FF_NAME = new Regex("( - Mozilla Firefox)$"); //new Regex("Firefox Name regex based on name taken from Inspect");
private const string PROXY_CLASSNAME = "MozillaDialogClass";//"Proxy window ClassName taken from Inspect";
private const string PROXY_AUTOMATIONID = null;//"Proxy window AutomationId taken from Inspect";
private static readonly Regex PROXY_NAME = new Regex("^(Authentication Required)$");//new Regex("Proxy window Name regex based on name taken from Inspect");
public FirefoxAutomation()
{
SubscribeTopLevelWindowOpened();
}
private void SubscribeTopLevelWindowOpened()
{
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement, TreeScope.Children, TopLevelWindowOpened);
}
private void TopLevelWindowOpened(object sender, AutomationEventArgs e)
{
var element = sender as AutomationElement;
if (element == null) return;
// Filter for FireFox window element
if (!MatchWindow(element, FF_CLASSNAME, FF_AUTOMATIONID, FF_NAME)) return;
// Subscribe for child window opened even
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
element, TreeScope.Children, FireFoxChildWindowOpened);
}
private void FireFoxChildWindowOpened(object sender, AutomationEventArgs e)
{
var element = sender as AutomationElement;
if (element == null) return;
// Filter for a proxy message
if (!MatchWindow(element, PROXY_CLASSNAME, PROXY_AUTOMATIONID, PROXY_NAME)) return;
// Find the cancel button
var controls = element.FindAll(TreeScope.Children, Condition.TrueCondition).Cast<AutomationElement>().ToList();
var cancelButton = controls.FirstOrDefault(c => c.Current.ControlType == ControlType.Button && c.Current.Name == "Cancel");
if (cancelButton == null) return;
// Get the click pattern
object clickPatternObj;
if (!cancelButton.TryGetCurrentPattern(InvokePattern.Pattern, out clickPatternObj)) return;
((InvokePattern)clickPatternObj).Invoke(); // click the cancel button
}
private bool MatchWindow(AutomationElement element, string className, string automationId, Regex name)
{
var current = element.Current;
if (current.ControlType != ControlType.Window) return false;
if (className != null && current.ClassName != className) return false;
if (automationId != null && current.AutomationId != automationId) return false;
if (name != null && name.IsMatch(current.Name)) return false;
return true;
}
}
}
Navigate to the website like this:
WebDriver.Navigate().GoToUrl("http://username:password#website.com");
The website.com would be the usual website.
If you do not want to log in you can just use an Action to send an Escape key to the driver:
var action = new Actions(WebDriver);
action.SendKeys(Keys.ESCAPE).Build().Perform();
I am writing a toolbar for IE(6+). I have used the various sample bars from
codeproject.com (http://www.codeproject.com/KB/dotnet/IE_toolbar.aspx), and have a toolbar that works, registers unregisters etc. What I want the toolbar to do is to highlight divs within an html page as the users' mouse moves over that div. So far the highlighting code works, but I would like to display the name of the div (if it exists) in a label on the toolbar (changing as the mouse moves etc).
I cannot for the life of me get this to happen and trying to debug it is a nightmare. As the assembly is hosted in IE, I suspect that I am causing an exception (in IE) by trying to update the text on the label from a thread that didn't create that control, but because that exception is happening in IE, I don't see it.
Is the solution to try to update the control in a thread-safe way using Invoke? If so how?
Here is the event code:
private void Explorer_MouseOverEvent(mshtml.IHTMLEventObj e)
{
mshtml.IHTMLDocument2 doc = this.Explorer.Document as IHTMLDocument2;
element = doc.elementFromPoint(e.clientX, e.clientY);
if (element.tagName.Equals("DIV", StringComparison.InvariantCultureIgnoreCase))
{
element.style.border = "thin solid blue;";
if (element.className != null)
{
UpdateToolstrip(element.className);
}
}
e.returnValue = false;
}
and here is an attempt at thread-safe update of the toolbar:
delegate void UpdateToolstripDelegate(string text);
public void UpdateToolstrip(string text)
{
if (this.toolStripLabel1.InvokeRequired == false)
{
this.toolStripLabel1.Text = text;
}
else
{
this.Invoke(new UpdateToolstripDelegate(UpdateToolstrip), new object[] { text });
}
}
Any suggestions much appreciated.
I can't really reproduce the issue (creating a test project for an IE toolbar is a tad too much work), but you can try this:
Add the following routine to a public static (extensions methods) class:
public static void Invoke(this Control control, MethodInvoker methodInvoker)
{
if (control.InvokeRequired)
control.Invoke(methodInvoker);
else
methodInvoker();
}
And then replace the section of similar code in the first block with this:
if (element.className != null)
{
this.Invoke(() => toolStripLabel1.Text = element.className);
}
This is a sure-fire way of avoiding thread-safe issues in UI applications.