I am modifying some old VB6 code and there are a number of calls to a subroutine called SDKPress(Index as integer, PressStatus as Integer, PressX as double, PressY as double, PressDataX as double, PressDataY as double).
(This routine returns the position of the mouse click and Index returns which graph on a form the mouse is in.)
Since there is no code for this in the project, I assume it is from some Windows software development kit. However, there is no trace of it on the development PC. just an SDK directory in the VisualBasic directory containing winsdk_web.exe.
I cannot call that subroutine from another project. Where does the subroutine live? Where can I find documentation on it? How can I get it in a form where I can use it on another project?
To find out where it lives. Put the cursor in one of the routine calls in the IDE, right-click on it, and choose go to definition. See where it takes you.
It may be an ordinary routine in a code file in your project.
It may be a routine in a DLL which is imported into your project via a Declare statement.
It may be a routine in a COM/ActiveX DLL or OCX control or even ActiveX EXE. In which case the IDE will show you the "object browser" window and you should be able to figure out where the routine lives, and go from there. I.e. figure out how to add a reference to it into another VB project, and how to install/register the relevant DLL/OCX/EXE on another PC.
OR, and I'm sure you tried this already, but just in case, search the source code for the routine name. Use Ctr-F or menu item Edit-Find in the VB IDE.
DLL files contains the API functions, vb6 code will load the DLL (Declare Function SDKPress Lib "DLLName" ....) and call the functions, use a tool like DllExpView: https://www.nirsoft.net/utils/dll_export_viewer.html and list DLLs and their functions. Or it also might be an internal subroutine/function.
If the original program which uses the SDK runs, you can gather some information using Process Monitor and Process Explorer. These can help you locate dependencies of many types.
I'd start with the second - when you run your program, ProcExp will show you all the files, including DLLs, that are loaded into the process. This alone might give you some insight.
If that is insufficient then use ProcMon to actively monitor the activities of your program. While ProcExp is basically a snapshot in time, ProcMon will dynamically record many of the actions of your program, including how it searches for and ultimately loads DLLs.
https://learn.microsoft.com/en-us/sysinternals/downloads/procmon
https://learn.microsoft.com/en-us/sysinternals/downloads/process-explorer
I have found these tools to be invaluable on many occasions. They help to break down the "black box" around a running process which appears in many programmers minds.
Related
I am working on greatly simplifying an old MFC application, and I'd like to use that opportunity to remove a dependency on a certain third-party ActiveX library that has been causing headaches. I first simply tried to remove all references to these controls in the cpp code. It compiles fine, but when installed on a new computer, it crashes if the library .msm file is not included in the setup project.
The problem now is that I don't know where any remaining references to these objects in the project is, and therefore have no easy way of tracking them down and removing them. Simply using the Find-functionality in VS only returns results in cpp files which I've already cleaned up, not any control instances in f.ex. dialog resource files. Is there a way to search for all these objects in the project, or check for them compile-time so that I can use compile errors to see where any library objects remain?
First of all: CoCreateInstance, CoGetClassObject are the normal ways how COM Objects are created. Should be easy to set break points here or to set a hook to monitor what's going on.
Seams that you have a bad error handling in you software. Otherwise you application should show an error message if an object could not be created.
Try to debug.... use remote debugging, even a crash dump will lead you to the code location.
Easiest approach: In your development machine. Try to look into the output window and see if any of the old ActiveX DLLs gets loaded. Trigger down to the location were any of those objects is created.
You can do the same with remote debugging on the test machine.
Running Excel 2010, I can assuredly always be running these sheets on this version, as it will only be accessed locally exclusively on my work's terminal computers.
I run a number of import process and large folder filtering/printing batch functions via excel. I am wanting to utilize the Windows 7 taskbar progress bar visual while my functions process, giving an idea of how far they are along. Considered going with other visual effects for showing the progress, but this(if possible) seems the most obvious and professional style to do so.
I've been looking thoroughly into trying to make this work, to no avail. My understanding thus far is that I need to impliment the ITaskbarList3 interface, commonly found within the Windows API. From the code I have found showing how to make it work, once implimented the rest seems fairly easy and self-explanatory.
I am completely restricted to using Excel as the basis for the code, no installation permission on the work computers. I can install at home to get any files necessary, and then transfer them. Happy to use any extensive or really backwards ways to get to the end, as the ends justify whatever means it takes.
It would be much easier to use the Excel Status Bar:
Application.StatusBar = "Show progress to user...";
For the Windows & Taskbar progress bar you need to download the
Windows 7 taskbar: Developer Resources.
You'll need to open the sample solution, right click on the Windows7.DesktopIntegration project > properties > Build > Tick Register for COM.
By checking the "Register for COM interop" option in the IDE during development, the IDE will call regasm on the target assembly together with the /codebase option.
This will cause regasm.exe to add the following registry entry for a COM-visible class exported from your assembly :
HKEY_CLASSES_ROOT\CLSID{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\InprocServer32\CodeBase=
This will enable the CLR to locate your assembly by following the path to your assembly.
Without the codebase path, the CLR will have to locate your assembly (and its dependencies) using the standard search algorithm.
Next Build the solution > goto the bin folder the Windows7.DesktopIntegration project and copy the Windows7.DesktopIntegration.DLL and Windows7.DesktopIntegration.TLB to the System32 folder or better yet Register to the GAC.
One related technique that helps the CLR to locate required assemblies is to copy all assemblies (and their dependencies) to the same folder as the client application itself. However, the client application in your case will be Excel. This means that you must copy the assemblies into the same folder as the Excel application (not a good idea).
Once you are able to instantiate the Windows7.DesktopIntegration DLL, you should be able to call the Windows7Taskbar.SetProgressValue method, eg VBA code:
Set Windows7Taskbar = CreateObject("Windows7.DesktopIntegration")
Windows7Taskbar.SetProgressState(form.Handle, Windows7Taskbar.ThumbnailProgressState.Normal)
Windows7Taskbar.SetProgressValue(form.Handle, progress, maximum)
I've been handed an application to support, and I'm trying to figure out how to do it. I do have the source, and can make some changes, but I obviously don't want to completely change the architecture of the application.
The app is in a VS2010 solution composed of 9 different projects. The main one is a Windows Form application, but it spins off others in other threads.
Here's the difficulty. Even though the different projects are parts of the same solution, they are separate executables, not DLLs. When the main program starts one of the other projects, it does so by creating a new process, setting the filename of the executeable, the startup arguments and other assorted parameters into the process.StartInfo object, and then calls process.Start().
How can I set breakpoints and debug subordinate executables? I can't attach to them until they are loaded, but they don't get loaded until process.Start() is called, and by then it's too late. Is there a method call I can insert into the main program to get it to load the executable (so I can set breakpoints in it) before it actually begins execution?
Thanks.
Are you able to recompile the other executables? If so, have you tried putting DebugBreak in suitable places? (or _asm int 3).
You can't load the process (usefully), since by definition it will be run in a different addres space from the one you are debugging before it starts.
One simple solution could be adding a call to DebugActiveProcess function to the "main" function of every process which participates in your application.
I'm using windbg to examine some crash dumps sent in by an app. There seems to be some correlation between a crash I'm seeing and having a certain 3rd party DLL loaded into the process (a flaky Winsock LSP, I suspect). To make this sort of analysis easier in the future, is there a windbg script that would just show me a list of modules that are non-Microsoft? This would make patterns between crashes more obvious to me. I'm using "lm D sm", but going through the list manually right now is a pain.
Thanks!
Try using "lm e" with your symbol path set to Microsoft's symbol server (and with only MS symbols loaded). That will cause WinDbg to show a list of all modules with any sort of symbol "problem" including modules that have not been loaded.
The keys to making this work are:
The sympath is only set to use the MS symbol store (use ".symfix" to achieve this)
Symbols have been loaded using the above sympath
From there you can add on the other options for "lm" to get info like full path, etc.
You can use cdb to script the debugger, and it just prints to stdout - open the crash dump, have it print the loaded module list then exit, then you can use your favorite text manipulation tool (hint: its name is Perl ;) ) to search the list.
EDIT: Just to add some extra info, cdb is the command-line version of WinDbg; they both use the same engine, it's just a different frontend.
I'm not sure I see why you want to do this, but you can output from WinDbg to a log and correlate with a list of DLLs. That's pretty easy to do in any scripting language such as Perl, Python etc.
The way that I do this now is I run sos.dll from the CLR10 directory from the Debugging Tools for Windows installation.
.load clr10\sos
!sam c:\temp\modules
I open the directory c:\temp\modules in Windows Explorer. I right click in the Header column and I add the column for Company. Then I sort on company and move DLLs with Company of "Microsoft Corporation" into a separate subdirectory called "Microsoft"
Whatever DLLs are left in the Directory are usually 3rd Party or custom developed code.
Thanks,
Aaron
I wrote a small command-line app to solve exactly this problem a while back.
http://www.sleep1000.com/software/dumpmod
We're going through a massive migration project at the minute and trying to validate the code that is deployed to the live estate matches the code we have in source control.
Obviously the .net code is easy to compare because we can disassemble. I don't believe this is possible in vb6 exes because of the manner of compilation.
Does anyone have any ideas on how I could validate the source code and the compiled executable matches the file I have in Live.
Thanks
Visual Basic had (has) two ways of compiling, one to the interpreter ( called P-code) that would result in smaller binaries, and a second one that generates "regular" windows .exe file (called native) that was introduced because it was supposed to be fastar than p-code; although the compiled file size increased with this option.
If your compilation was using p-code, it is in theory possible to restore the sources.
Either way is pretty difficult to do, but there are tools that claim they can partially do this, one that I know of ( never tried but there is a trial version ) is VB-decompiler
http://www.vb-decompiler.org/
Unfortunately that's almost impossible. Bear in mind that VB6 code compiled on different machines will have different exe sizes and deployment requirements.
This is why the old VB'ers had a dedicated machine to compile their code.
This won't help you with already deployed items, but if you upped the revision number on every compile (there is a project setting to do this for you automatically) then you could easily compare version numbers.
My old company bought a copy of that VB-Decompiler and as noted before VB5/6 generates P-Code extra, that tool did produce some code and if not Assembly code which could be "read".
If you have all the code you compiled, you could compare the CRC's of that code to what is deployed in the field. But if you don't have the original compiled code, depending upon how you compiled the code you (if you used P-Code rather than Native Code you may be able to disassemble but the disassembly will look nothing like your source code). I doubt you would have shipped the PDB's with the exe's, but if you did, you could certainly use those to compare with the source code in your repository.
Have a trusted computer that can check out the various libraries and exes you make and compile them automatically. Keep those in a read-only but accessible location. Then do a binary comparison between the deployed site and your comparison site.
However I am not sure of the logic over disassembling the the complied units. My company and most other places I know of use a combination of a build computer and unit testing. In our company the EXE we make is a very thin shell over a bunch of libraries. For example a button click will be passed to a UI Active X DLL that does the actual processing. What we do after a build is run a special EXE that perform our list of unit test. If they all passed we know our libraries, where 90% of our code is, are good. As for the actual EXE we have a hand procedure that takes about two hours to do and then we are good. IIt is rare for any errors to happen in the EXE.