CreateProcess vs Command Line and missing DLL - winapi

When I use CreateProcess to start an application (InDesign) that is loading my plug-in, my plugin fails to load because a DLL my plugin uses can't be loaded. The strange thing is that if I double click the application or open it from a command line, my plugin loads fine.
My application that calls CreateProcess is quite large and itself uses several DLLs some of which are also used by my plug-in. I've narrowed it to the DLL that will will not load. I set it to delay load, the plugin now loads but will not load that DLL when I call it.
I've used "Process Explorer" to check out the application's PATH to make sure it's the same as when I open it from the command line. The path to the trouble DLL is in the PATH env, this is the same for other DLLs that load fine.
I launch many different apps with and without my plugins and have never seen something like this before.
Anybody know what might be going on?
Oops...
Well, I was wrong about the env PATH, it was different depending on how the application (InDesign) was launched. It looks like QuickTime changes the PATH for my application, placing it's "Apple Application Support" folder at the top. Inside that folder is a DLL with the same name as the one I'm using, namely libxml2.dll. When I load libxml2.dll in my plugin using LoadLibrary, msvcr80.dll can't be found. Shish.
Sorry for the distraction...

Check the working path when loading the application and/or plugin. Explorer and the command prompt normally set this explicitly but another application calling CreateProcess() may not.

Related

VB6 Service debugging with WINDBG

First and foremost, I'm an absolute newbie at debugging compiled code (until recently, I didn't even know it was possible!). I've successfully used the VC6 IDE to attach to a process but I can't get WinDbg to work...
The problem is that I have a VB6 service that I need to debug in a production server. I really don't understand much of how the .EXE is compiled because it is generated by an external tool called "NT Service Toolkit". The code I have is compiled into an ActiveX DLL that is used by this .EXE.
I've done everything I found on the internet to make the service debuggable with the VC6 IDE: compile without optimizations and generate symbols. When I use the VC6 IDE to attach to it, it works as expected... I can set breakpoints and everything works fine except for the annoying bug that kills the service when the debugging session stops.
When I try to use WinDbg however, I cannot set breakpoints; it fails with an error:
Unable to insert breakpoint 0 at 00000000`0046f715, Win32 error 0n299
"Only part of a ReadProcessMemory or WriteProcessMemory request was completed."
bp0 at 00000000`0046f715 failed
WaitForEvent failed
I've already downloaded symbols for windows' components from the symbol servers, as instructed in the documentation I could find, and I also included the PDB file for my service in the symbols folder...
One thing I noted is that I can get symbolic information when I check the "Noninvasive" box when selecting the process to attach to because I see things like wow64win!ZwUserGetMessage instead of just the address`offset syntax... but when I do, I also get this warning:
WARNING: Process <PID> is not attached as a debuggee
The process can be examined but debug events will not be received
In this case, I can set breakpoints, but when I try to run the service, it fails with:
0:000> g
^ No runnable debuggees error in 'g'
UPDATE
When I set a breakpoint in "Noninvasive" mode, detach, and reattach with "Noninvasive" un-checked, the breakpoints I set while in "Noninvasive" mode remain, and are hit successfully, but I can't set new breakpoints unless I repeat the whole process (detach, attach in "Noninvasive" mode and reattach). Does this make sense? What could I be doing wrong?
I found the problem. It was a conflict in the module names.
When WinDbg loads the modules for a process, it names them as the file where they live, just WITHOUT extension. Therefore, if, as in my case, two modules that must be loaded share the same name, say MyService.exe and MyService.dll, there will be two modules named MyService; in this case, WinDbg breaks the ambiguity by appending _<start-address> to the name, resulting in, for example:
...
MyService
MyService_11000000
...
(The following is a rationalization of what happened, since like I said, I'm pretty new to "attach to process"-type debugging and I lack knowledge of WinDbg internals...)
My problem was that the PDB file for the DLL (MyService.pdb), which was the module I was interested in debugging, was being matched to the EXE file's module (MyService), so the DLL's symbols were not loaded before trying to "restore" the breakpoints, resulting in the Win32 error 0n299 I was seeing earlier... It appears that the g command also tries to "set" the saved breakpoints, and since the symbols were not yet loaded, it would not let me start the thing after the default breakpoint either...
...
Or something like that... Obviously, if someone has a more accurate explanation, I'd very much like to be enlightened. :)
For the moment, I just changed the service EXE's name, and now everything works fine.

Developing Reg-Free COM application with VB6

I'm maintaining a VB6 application with many COM components (DLLs and OCXs). In order to streamline development and deployment I'd like to use reg-free com. The problem with development is that the application runs within the VB6.EXE instance. How can I trick VB6 to use my (unregistered) components? It is very important for me to not have to go through registering/unregistering components when switching between branches. Generating a .manifest file for VB6 is not out of the question but is there some other, more optimal way, to specify a .manifest file when launching VB6.EXE?
Note: The Activation Context API doesn't seem to help, even if used from within the development environment.
Solutions I've thought:
A utility application that activates a context from a manifest and launches VB6 as a child process (doesn't work; processes don't inherit activation context)
Injecting context activation into the VB6 process at startup (too complicated; must hack the executable to do this)
Hosting VB6 in my own process after activating the right context (can't even find out if this is possible)
Using a VB6 Add-In or other utility that runs within VB6 to activate a context (tried that but it doesn't seem to work)
Update Jan. 16
As suggested by wqw, I did some testing with a VB.exe.manifest. The VB6.exe.manifest worked, with some caveats:
The SxS dll specified in the manifest would not appear in the references window on projects that didn't actually reference the component
On projects that did reference the component it would be shown to reside in the directory according to the following order:
The pathname recorded in the project file (if the file was still present)
A pathname as if it resided in the same folder as the project (vbp)
If the file was not in any of these folders, the project would not compile (just running the code causes an internal compile in VB6) with the message "Can't find project or library".
Obviously, VB6 actualy scans the registry to find COM components and verifies, during compilation, that they exist where they say they exist. I'm not sure what that might mean if I actually want to use VB6.exe.manifest to redirect COM component instantiation. Perhaps having dummy component files at some predefined location might trick VB6 into believing that everything is as it should be, although an entirely different set of components got loaded for use.
Further update:
I did a test on that last assumption and it proved to be false. The component has to actually be there in order for the project to compile. It must even properly load (no dummy, zero-length files accepted!). Now I'm not even sure if the manifest works. That's a more time-consuming test (requires a component with two versions that produce different results, one with the project, and one for the manifest).
Our approach to this problem was to write a build assist program that registered and unregistered components, run the VB6 compiler, and would even rewrite project files with updated GUIDs when interfaces changed. You would hand it a VBG project group and it would do the rest.
I suppose we could also have added a mode that unregistered components when you switched branches.
Are you following the practice of using "compatibility" binaries? You shouldn't use the binary at your build location for compatibility references - you should commit a separate copy to version control and configure your project to consider that the "compatible" version - only change this file when you break interfaces.

How to use external Dll in Air Native Extension?

The structure of my ANE file looks like this:
<META-INF>
<ANE>
<Windows-x86>
ExtensionDll.dll
DllUsedByExtensionDll.dll
extension.xml
mimetype
catalog.xml
library.swf
If ExtensionDll.dll uses the functions in the other Dll, the extension won't load. DllMain is not called. It seems like DllUsedByExtensionDll.dll is not in the Dll search path when the air application uses the extension is running.
How should I make the application find the extra Dlls, if I don't want to put them into some common Dll path?
I've had the same problem and went at this for a few days. Turns out there's two ways to solve this.
Export Release Build, while making sure that the DllUsedByExtensionDll.dll is packaged in the same directory as your executable.
For debugging purposes, copy the DllUsedByExtensionDll.dll into your Adobe AIR SDK bin directory, where the Air Debug Launcher (adl) executable is located.
You do not need to package DllUsedByExtensionDll.dll in the ANE that you are building.
The problem is that ExtensionDll.dll cannot find the DllUsedByExtensionDll.dll when it is launched from the debugger, since the executable for the debugger is located in the AIR SDK. Once you export the release build however, the your app is the executable, so now it looks for the dll in its root directory.
If you want to debug this in order to find out more information on what could be wrong, I suggest that you run your app by command line using the adl command.
For me, running through Flash Builder's debug/run meant that I could not see the Windows error "the program can't start because dll is missing from your computer". And that led me on a wild goose chase for a long time.
If your dll is using other dlls then include the reference dll's in the project where you are going to use that ANE file.

Why does my dll end up in AppData\Local\Temp\

I have a small SWT based java application. On installation swt-win32-*.dll is installed with my application in C:\Program Files\myapp\win32.
When I looked at my application in process explorer I noticed that the dll is loaded from:
C:\Users\[Username]\AppData\Local\Temp\swtlib-32\swt-win32-*.dll
On Windows XP it ends up in:
C:\Documents and Settings\[Username]\Local Settings\Temp\swt-win32-*.dll
Whenever I delete it from the temp folder and restart my application the dll is copied there again. The other dlls my application depends on don't show this behaviour.
Who copies the dll (my application doesn't)?
What's the reason behind it?
I don't know Java very well, but if it's inside the JAR (or any kind of archive, really), then it has to be extracted into real file before it can be loaded (because OS provides no other supported way to do it).

What are the differences between running an executable from a Windows Command Prompt versus from Windows Explorer?

EDIT: This is due to stupidity. It is a multiple monitor issue. It's just that from cmd.exe we always opened in the primary monitor, whilst from explorer, we always opened in the secondary. Thanks all for the help!
We hit a weird bug recently. We have a Qt + osg app that behaves differently if we run it from explorer than if we run it from a command line. Running from explorer is unusable, while running from command line (or by running from the explorer a simple batch file that calls the .exe) works as expected.
We suspect environment variables, because that's all we can think of. But the fact that it runs fine with a one line batch file seems to refute this. I'm not familiar enough with windows to know of any subtle differences in how it loads executables, nor where to look to find out.
Are there any other differences that could explain this? Does windows load different sets of user environment variables in each case? OS is Windows XP Service Pack 3.
The behavior experienced when running from explorer (double click program.exe) is consistent with a driver issue or improper OSG scene setup: image artifacts, flashing, and weird colors.
The behavior experienced when running the same executable from cmd.exe (or by double clicking a .bat file next to the .exe containing only a line to run the .exe) is the correct, expected behavior: the scene is correct, no flashing, etc.
To rule out potential library load path issues, try using dot-local DLL redirection.
Towards that end, create an (empty) file in the same directory as your executable and give it the same name as your binary, except with .local appended. I.e., if your binary is named yourbinary.exe, name that file yourbinary.exe.local. That will force the PE loader to first look in that directory to resolve LoadLibrary calls (and that includes DLLs loaded indirectly via system DLLs or via COM, no matter how many indirection levels are involved.) Place as many supporting DLLs (including Qt DLLs) in that directory. If you're using Qt plugins, also place the plugins directory there (or use a custom trolltech.conf.)
More details on dot-local redirection here, for example.
This thread looks like it might have the answer to your question:
http://forum.soft32.com/windows/Start-Run-Command-Prompt-ftopict353085.html
In short, I think it might be looking for your executable in different places depending on which method you attempt to use to run it. Perhaps you have 2 different versions hiding somewhere that explorer uses instead of the one you want?
You have not given enough details so I will give you a general answer. In order to use QT and its tools you need 2 environment variables. *QTDIR, and PATH * Make sure you have these variables set instructions are below. I have taken them from this site. See also this link for deployment on windows.
Setup the QTDIR environmental
variable.
1) Create a new System variable
called: QTDIR
a. Right click on My Computer -> Properties -> Advanced Tab ->
Environment Variables button
b. Find System variables -> New -> Type in "QTDIR" 2) Set the value to: C:\your\Qt\directory (NOTICE: No
trailing '\' character!!!)
Now, add the QTDIR on to your PATH
variable.
1) Edit your PATH variable, add onto
the end of it a ';' if one isn't
already on the end. 2) Now add on:
%QTDIR%\bin;
Example:
Before
PATH=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;
After,
PATH=%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%QTDIR%\bin;
That will make sure that our Qt
application(s) will be able to find
the Qt DLL files when you go to run
it.
I hope this helps.
Perhaps there is a difference caused by the way Explorer launches an executable vs directly running it from the console. I think that Explorer uses ShellExecute or ShellExecuteEx and I doubt that executing an application from a console or batch file does the same.
I would create a test app that tries some of the ShellExecute variants and use different parameters to see if the Explorer behavior can be reproduced in order to try to diagnose what parameters passed to ShellExecute might be causing the problem.
There is an interesting community note on the ShellExecuteEx page that may or may not be applicable:
ShellExecuteEx ignores the current input desktop. It always uses winsta0\default. Instead use ShellExecute or CreateProcess.
I would also investigate whether or not AppCompatFlags affect console executed applications (or see if any AppCompatFlags have been set for your application).

Resources