Window Messaging to Legacy Application - windows-messages

I developed an application of controlling other window using WindowsMessage. It works successfully with my sample application, which is build by C#.
However, then I tried to configure my controlling application with the legacy window, which is developed by VB6.0. Here I got 2 issues,
1) The following method returns false and textfield was not updated.
IntPtr wParam = IntPtr.Zero;
IntPtr lParam = Marshal.StringToHGlobalAuto(text);
bool retVal = Convert.ToBoolean(SendMessage(handle, WM_SETTEXT, wParam, lParam));
Can anybody help me to figure it out ?
2) When I scanned the sub-controllers in legacy application (using the window messaging),I found some controllers that their class names are ThunderRT6FormDC, ThunderRT6UserControlDC. What are these controllers ?

2) The ThunderRT6FormDC and ThunderRT6UserControlDC are Visual Basic specific class names: VB sprang from an original project called Thunder and so the name stuck with a lot of the bits and pieces of VB code. Many VB window classes have Thunder in the name, including the 2 you saw.
1) My expectation is that the handle you fetched is not pointing at the right window: are you using Spy++ or a similar tool to look at the VB6 window and determine the proper text window, or are you setting the focus to the text window before sending the WM_SETTEXT message?

Related

Setting up the TypePal type checker on Eclipse IDE

After implementing a type checker in Rascal using TypePal, how do I hook it up to the Eclipse IDE? Any resources or repositories to the solution to this problem would be appreciated, Thanks.
in Eclipse search path of the Rascal Navigator view in your project you will find the rascal_eclipse library which contains a good example: demo::lang::Pico::Plugin
in this module you see how to register a language with Eclipse:
registerLanguage("Pico Language", "pico", parsePico); where parsePico is a function reference. Pass your own parameters here. The registerLanguage function comes from util::IDE.
now you can open files with the "IMP editor" in Eclipse and they will use your parser and show syntax highlighting.
next up is registering other effects with the IDE. The library function to call is registerAnnotator. You pass it a function that takes a parse tree for your language and annotates it with error messages:
the messages may be distributed over the tree, using #message or
using a list of #messages at the top of the tree
the error messages will be added as annotations in the editor and registered with the Problem View automatically.
So you have to wire the output of TypePal into the annotator function yourself. Which should be a one-liner.
Alternatively, running type-checks can also be useful after a "save" action. In this case you can register another type of contribition (also in the Pico demo), called builder: builder(set[Message] ((&T<:Tree) tree) messages), and register that with the registerContributions function.
The Message ADT is the same for the annotator and the builder. Both have the effect of adding editor annotations and problems in the view.
Here is some example code taken from an older open-source DSL project called "Bird", https://github.com/SWAT-engineering/bird:
Tree checkBird(Tree input){
model = birdTModelFromTree(input, pathConf = config(input#\loc)); // your function that collects & solves
types = getFacts(model);
return input[#messages={*getMessages(model)}]
[#hyperlinks=getUseDef(model)]
[#docs=(l:"<prettyPrintAType(types[l])>" | l <- types)]
;
}
birdTModelFromTree calls collectAndSolve from TypePal and returns the TModel
getMessage comes from TypePal's Utilities and extracts a list[Message] from the TModel that can be directly communicated to Eclipse via the #messages annotation.
The entire checkBird function is registered as an annotator using the util::IDE function registerAnnotator.
This code hasn't been used for a while, so if you run into trouble, please contact again?

How to know the URL of a current Navigator

You are about to read many grammatical mistakes, sorry, I am not native to English language.
Hello, I am developing a simple software that counts the time you spend on applications, at the begin wasn't complicated, but now they request me to identify when the application is a navigator like Chrome, Firefox or IE. Then it has to identify what URL is currently in use to start count how much the user waste on all the open pages, but I don't know how to identify if is a navigator, obviously which URL is on it.
OUTPUT EXAMPLE (output.txt)
Process Used:
netbeans 00:04:43 <- Done
calc 00:23:12 <- Done
chrome(www.facebook.com) 00:01:02 <- Dont know how
chrome(www.9gag.com) 00:17:23 <- Dont know how
Global
[DllImport("user32.dll")]
public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out uint ProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
This is the way i get the current process name that is in use
GetWindowThreadProcessId(hwnd, out pid);
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById((int)pid);
String NOMBRE = p.ProcessName.ToString();
Hope some can help me. Thanks!
Really no easy answers. "Navigators" are called web browsers, to help you in searching.
For the OS, they are regular programs, nothing special. In particular, the OS has no idea about the URL currently shown. That's a good thing, btw - the introduction of tabbed browsing means that you often have multiple tabs and thus multiple URLs open at the same time. If the OS knew about "the URL" of a webbrowser, it would have had major issues with tabbed browsing.
A good idea is to compare the URL in a webbrowser with the current score in a game. Both are simple variables, conceptually, but the OS doesn't try to track game scores either.
You can of course implement such a thing per type of webbrowser, but it takes work.

Calling Delphi DLL crashes VB6 exe with "Run-time error '-2147418113 (8000ffff)' Method '~' of object '~' failed", but only on some machines!

I have searched for hours but could not find anything similar.
The crash has two flavors; one is with "Run-time error '-2147418113 (8000ffff)' Method '~' of object '~' failed" and the second flavor is a total crash where Windows asks if I want to report this to Microsoft. In the second case I chose to debug once and it showed "Unhandled exception in App.exe (OLEAUT32.DLL): 0xC0000005: Access violation."
The Disassembly screen showed the yellow pointer at top line of:
>> 771148A4 mov ecx, dword ptr [esi]
771148A6 add ecx, 15h
771148A9 and ecx, 0FFFFFFF0h
771148AC push ecx
771148AD push esi
...
The problem occurs when calling a particular essential function in a third-party Delphi DLL, but I cannot declare outright that the DLL is buggy because this happens only in the program executables I compile. This same dll is used in hundreds of other customers and (at least for now) I am the only one running into this problem. The same source code compiled in the customer's PC, or the 3rd party supplier's office works fine.
So the problem boils down to this: VB6 with SP6 produces different binary exe files from the exact same source code. The one compiled on my pc works fine in my pc, and a clean virtual pc I installed to check this, but does not work anywhere it should; and the one compiled in the customer or the 3rd party supplier works fine everywhere except my pc.
It is unlike the problem Boost describes (see this link) since both the IDE and the compiled application behave in the same manner on all machines. They either work fine or break terribly.
Public mXApp As XObjects.XApplication
Public Sub Main
On Error Resume Next
Set mXApp = New XObjects.XApplication
If Err.Number = 0 Then
MsgBox "Found: " & mXApp.Version & vbCrLf & mXApp.GetAppPath
Else
MsgBox "XApp DLL not found. " & Err.Number & ": " & Err.Description
End If
Err.Clear
End Sub
Public Sub Login(Byval uid As String, Byval pwd As String, Byval companyNr as Long)
Dim ok as Boolean
ok = mXApp.Login(uid, pwd, companyNr)' >> CRASH! Program never gets to the next line.'
If ok Then
MsgBox "Login success"
Else
MsgBox "Login fails"
End If
End Sub
Note that after the mXApp object is created, two function calls are done -namely Version and GetAppPath- without any problem. The crash occurs in the Login call. VB IDE Object browser displays the definitions of the three functions as:
Function Version() As String
Function GetAppPath() As String
Function Login(UserName As String, Password As String, FirmNr As Long) As Boolean
Does anyone have any solutions or (equally usefully) ways that I can make the supplier reproduce this problem in their own machines?
Well, it's hard to say for sure without being able to see the Delphi side of it, but when you get problems like this in DLL calls, there are two standard things to check first.
First, make sure the DLL function and the import header for it in the VB program are using the same calling convention. If VB is putting the paramters in one place and the Delphi DLL is looking for them somewhere else, you get undefined behavior.
Second, make sure you're using the same string type on both sides. If this is COM, your string type should be the COM BSTR type, known as WideString in Delphi. Not sure what VB calls it. If you're passing the DLL a different string type than it's expecting to receive, it'll get corrupt data.
Double-check these two things and see if that doesn't fix it.
Problem Solved! Mason was quite right when telling me to double-check:
...make sure the DLL function and the
import header for it in the VB program
are using the same calling convention.
If VB is putting the paramters in one
place and the Delphi DLL is looking
for them somewhere else, you get
undefined behavior.
The DLL on my pc and the one in the customer were slightly different builds all along. And I had assumed that they had exactly the same interface. But wait before thinking I was careless; I did not just assume this, I had compiled two different executables after registering both versions of the DLL long before posting my question here.
When I thought I had tried the second dll, I was mistaken. I had registered the dll version 1.1 on my pc. The Object Viewer showed the declarations in the question. I compiled the executable and tested. And then without exiting the IDE, I registered the dll version 1.2 and compiled again assuming that the VB compiler would read the dll interface during compilation. Well this assumption was wrong. It turns out that the IDE had to be restarted.
Problem was solved after the supplier of the dll told me there was an optional new parameter, but they did not mention it earlier assuming this would not be problem since it was optional.
Below is the difference that caused the crashes:
Function Login(UserName As String, Password As String, FirmNr As Long, [PeriodNr As Long]) As Boolean
Make sure you're loading the right DLL. Process Explorer from SysInternals will show you the DLLs being used by any app (configure it to show DLLs in the lower pane). Maybe you're loading a different version of the DLL, unknowingly.
You can run it directly here:
http://live.sysinternals.com/ click on procexp.exe

Sending the return key to an emulated console application

I'm using delphi to add an graphical interface to a console application.
The problem is when the console application asks for input.
I would normally type in my input and press enter to make it accept my string, but I don't know how to do this.
I'm using this library as a "wrapper" over the console application, it uses pipes for the input and output streams.
http://koders.com/delphi/fidDB05C6361540F62D532FC7C960D4111CE3AAEDB3.aspx?s=proxy
I've tried things like WriteToConsoleApp(#04); to send an EOT, which is Control-D. This would normally work but in this case it doesn't do anything.
I've also tried WriteToConsoleApp(#13); WriteToConsoleApp(#13#10);, but none of these solutions work.
If you have any advice I would be grateful.
You can use SendMessage or PostMessage function to send string/key to console application.
For example;
SendMessage(WindowHandle, WM_CHAR, Ord('A'), 0);//sends 'A' to the window
or
PostMessage(WindowHandle, WM_KEYDOWN, VK_RETURN, 0);//sends Return to the window

Find out what process registered a global hotkey? (Windows API)

As far as I've been able to find out, Windows doesn't offer an API function to tell what application has registered a global hotkey (via RegisterHotkey). I can only find out that a hotkey is registered if RegisterHotkey returns false, but not who "owns" the hotkey.
In the absence of a direct API, could there be a roundabout way? Windows maintains the handle associated with each registred hotkey - it's a little maddening that there should be no way of getting at this information.
Example of something that likely wouldn't work: send (simulate) a registered hotkey, then intercept the hotkey message Windows will send to the process that registered it. First, I don't think intercepting the message would reveal the destination window handle. Second, even if it were possible, it would be a bad thing to do, since sending hotkeys would trigger all sorts of potentially unwanted activity from various programs.
It's nothing critical, but I've seen frequent requests for such functionality, and have myself been a victim of applications that register hotkeys without even disclosing it anywhere in the UI or docs.
(Working in Delphi, and no more than an apprentice at WinAPI, please be kind.)
One possible way is to use the Visual Studio tool Spy++.
Give this a try:
Run the tool (for me, it's at C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\spyxx_amd64.exe or you can download it). Note: there is spyxx.exe (32-bit version) and spyxx_amd64.exe (64-bit version) - if you don't see anything in 64-bit use the 32-bit version (ie.catches messages only in same architecture)
In the menu bar, select Spy -> Log messages... (or hit Ctrl + M)
Check All Windows in System in the Additional Windows frame
Switch to the Messages tab
Click the Clear All button
Select WM_HOTKEY in the listbox, or check Keyboard in Message Groups (if you're OK with more potential noise)
Click the OK button
Press the hotkey in question (Win + R, for example)
Select the WM_HOTKEY line in the Messages (All Windows) window, right click, and select Properties... in the context menu
In the Message Properties dialog, click the Window Handle link (this will be the handle for the window that received the message)
Click the Synchronize button on the Window Properties dialog. This will show the window in the main Spy++ window treeview (if it's windows itself or some popup application it shows nothing).
On the Window Properties dialog, select the Process tab
Click the Process ID link. This will show you the process (In my Win + R case: EXPLORER)
Your question piqued my interest, so I've done a bit of digging and while, unfortunately I don't have a proper answer for you, I thought I'd share what I have.
I found this example of creating keyboard hook (in Delphi) written in 1998, but is compilable in Delphi 2007 with a couple of tweaks.
It's a DLL with a call to SetWindowsHookEx that passes through a callback function, which can then intercept key strokes: In this case, it's tinkering with them for fun, changing left cursor to right, etc. A simple app then calls the DLL and reports back its results based on a TTimer event. If you're interested I can post the Delphi 2007 based code.
It's well documented and commented and you potentially could use it as a basis of working out where a key press is going. If you could get the handle of the application that sent the key strokes, you could track it back that way. With that handle you'd be able to get the information you need quite easily.
Other apps have tried determining hotkeys by going through their Shortcuts since they can contain a Shortcut key, which is just another term for hotkey. However most applications don't tend to set this property so it might not return much. If you are interested in that route, Delphi has access to IShellLink COM interface which you could use to load a shortcut up from and get its hotkey:
uses ShlObj, ComObj, ShellAPI, ActiveX, CommCtrl;
procedure GetShellLinkHotKey;
var
LinkFile : WideString;
SL: IShellLink;
PF: IPersistFile;
HotKey : Word;
HotKeyMod: Byte;
HotKeyText : string;
begin
LinkFile := 'C:\Temp\Temp.lnk';
OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, SL));
// The IShellLink implementer must also support the IPersistFile
// interface. Get an interface pointer to it.
PF := SL as IPersistFile;
// Load file into IPersistFile object
OleCheck(PF.Load(PWideChar(LinkFile), STGM_READ));
// Resolve the link by calling the Resolve interface function.
OleCheck(SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI));
// Get hotkey info
OleCheck(SL.GetHotKey(HotKey));
// Extract the HotKey and Modifier properties.
HotKeyText := '';
HotKeyMod := Hi(HotKey);
if (HotKeyMod and HOTKEYF_ALT) = HOTKEYF_ALT then
HotKeyText := 'ALT+';
if (HotKeyMod and HOTKEYF_CONTROL) = HOTKEYF_CONTROL then
HotKeyText := HotKeyText + 'CTRL+';
if (HotKeyMod and HOTKEYF_SHIFT) = HOTKEYF_SHIFT then
HotKeyText := HotKeyText + 'SHIFT+';
if (HotKeyMod and HOTKEYF_EXT) = HOTKEYF_EXT then
HotKeyText := HotKeyText + 'Extended+';
HotKeyText := HotKeyText + Char(Lo(HotKey));
if (HotKeyText = '') or (HotKeyText = #0) then
HotKeyText := 'None';
ShowMessage('Shortcut Key - ' + HotKeyText);
end;
If you've got access to Safari Books Online, there is a good section about working with shortcuts / shell links in the Borland Delphi 6 Developer's Guide by Steve Teixeira and Xavier Pacheco. My example above is a butchered version from there and this site.
Hope that helps!
After some research, it appears that you'd need to get access to the internal structure that MS uses to store the hotkeys. ReactOS has a clean room implementation that implements the GetHotKey call by iterating an internal list and extracting the hotkey that matches the parameters to the call.
Depending on how close ReactOS' implementation is to the MS implementation, you may be able to poke around in memory to find the structure, but that's over my head...
BOOL FASTCALL
GetHotKey (UINT fsModifiers,
UINT vk,
struct _ETHREAD **Thread,
HWND *hWnd,
int *id)
{
PHOT_KEY_ITEM HotKeyItem;
LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
{
if (HotKeyItem->fsModifiers == fsModifiers &&
HotKeyItem->vk == vk)
{
if (Thread != NULL)
*Thread = HotKeyItem->Thread;
if (hWnd != NULL)
*hWnd = HotKeyItem->hWnd;
if (id != NULL)
*id = HotKeyItem->id;
return TRUE;
}
}
return FALSE;
}
I presume this thread on sysinternals was asked by someone related to this question, but I thought I'd link to it anyway to keep the two together. The thread looks very intriguing, but I suspect that some deep dive spelunking would need to happen to figure this out without access to the MS internals.
Off the top of my head, you might try enumerating all windows with EnumWindows, then in the callback, send WM_GETHOTKEY to each window.
Edit: Apparrently I was wrong about that. MSDN has more information:
WM_HOTKEY is unrelated to the WM_GETHOTKEY and WM_SETHOTKEY hot keys. The WM_HOTKEY message is sent for generic hot keys while the WM_SETHOTKEY and WM_GETHOTKEY messages relate to window activation hot keys.
Note: Here is a program purporting to have the functionality you are looking for. You could try decompiling it.
Another thread mentions a global NT level keyboard hook:
Re-assign/override hotkey (Win + L) to lock windows
maybe you can get the handle of the process that called the hook that way, which you can then resolve to the process name
(disclaimer: I had it in my bookmarks, haven't really tried/tested)
I know you can intercept the stream of messages in any window within your own process - what we used to call subclassing in VB6. (Though I do not remember the function, perhaps SetWindowLong?) I am unsure if you can do this for windows outside your own process. But for the sake of this post lets assume you find a way to do that. Then you can simply intercept the messages for all top level windows, monitor for the WM_HOTKEY message. You wouldn't be able to know all the keys right off the bat, but as they were pressed you could easily figure out what application was using them. If you persisted your results to disk and reloaded each time your monitor application was run you could increase the performance of your application over time.
This doesn't exactly answer the part of the question that is about the Windows API, but it answers the part of the question that is about a list of global hotkeys and the applications that "own" them.
The free Hotkey Explorer at http://hkcmdr.anymania.com/ shows a list of all global hotkeys and the applications that own them. This just has helped me figure out why an application-specific shortcut key stopped working and how to fix it (by reconfiguring the registered global hotkey in the app that had it registered), within a few seconds.

Resources