I am trying to simulate a mouse event on Win7, and my application uses the open source Windows Input Simulator project on the website http://inputsimulator.codeplex.com/ , which internally uses the codes below to simulate a mouse event:
[DllImport("user32.dll", SetLastError = true)] public static extern UInt32 SendInput(UInt32 numberOfInputs, INPUT[] inputs, Int32 sizeOfInputStructure);
My application works fine when I debug it using Visual Studio 2010. The left-click event, the right-click event, and the mouse move event are fine. But click events are not dispatched when I launch my application from Explorer by double-clicking the excutable application .exe file. Only the mouse move event is fine, if I try to simulate a left click or a right click, my application will get an exception and exit. I found that the exception is thrown by the codes below:
public void DispatchInput(INPUT[] inputs) { if (inputs == null) throw new ArgumentNullException("inputs"); if (inputs.Length == 0) throw new ArgumentException("The input array was empty", "inputs"); var successful = NativeMethods.SendInput((UInt32)inputs.Length, inputs, Marshal.SizeOf(typeof (INPUT))); if (successful != inputs.Length) throw new Exception("Some simulated input commands were not sent successfully. The most common reason for this happening are the security features of Windows including User Interface Privacy Isolation (UIPI). Your application can only send commands to applications of the same or lower elevation. Similarly certain commands are restricted to Accessibility/UIAutomation applications. Refer to the project home page and the code samples for more information."); }
This suggests that UIPI has blocked SendInput (...). So I google this thread and get some tips.
1) Add uiAccess = "true" to my application manifest
<requestedExecutionLevel level="requireAdministrator" uiAccess="true" />
2) Create a test certificate and add this certificate to the certificate store of trusted root certificate authorities and the certificate store of trusted publishers.
MakeCert -r -pe -ss PrivateCertStore -n "CN=Test Certificate - For Internal Use Only" testcert.cer CertMgr.exe /add testcert.cer /s /r localMachine root CertMgr.exe /add testcert.cer /s /r localMachine trustedpublisher
3) Sign my app with a previous digital signature
SignTool sign /v /s PrivateCertStore /n "Test Certificate - For Internal Use Only" /t http://timestamp.verisign.com/scripts/timestamp.dll MyApplication.exe
4) Install my application in the folder "C: \ Program Files", which is one of the safe places on my computer.
I think I did everything to satisfy the requirements of UIPI, but the problem is still not resolved after I launched the application and agree with the UAC request. Only the mouse move event is OK.
PS: if I do not sign my application with a test certificate and add only "requestExecutionLevel" with uiAccess = "true" in the manifest, the application does not start, and Windows displays a dialog with the message "The referral was returned from the server.". If I sign my application with a test certificate, UAC will work when I run the application. The application will work until I call SendInput to simulate a click event and then throw an exception.
I read the requirements "UI Privilege Isolation and Integrity" at http://msdn.microsoft.com/en-us/library/bb625963.aspx , but it still doesn't work after that.
I found a blog. This blog post says:
By specifying UIAccess = "true" in the requestPrivileges attribute [application manifest], the application states that it is necessary to bypass UIPI restrictions when sending window messages through privilege levels. Windows Vista performs the following policy checks before running the application with the UIAccess privilege. The application must be digitally signed, which can be verified using a digital certificate that connects to a trusted root on the local computer. Trusted Root Certification Authority Storage. The application must be installed in the application directory of the local folder, which can only be written by administrators, such as the Program Files directory.
Unfortunately, this will not work if the application can be installed by users who are not administrators.
I want to know how to make my application inconsistent with the last sentence "Unfortunately, this will not work if the application can be installed by users without an administrator" and can bypass UIPI by adding uiAccess = "true" to the manifest.
Can anybody help me?