Best Practice - Where to place a managed assembly when real purpose is to expose TLB file - com

I have an environment where there is a combination of managed and non-managed executables being run for a particular suite.
I have a scenario where the only reason I have a managed assembly (in this case) is because code was easier to write in C# than in VB6.
My 'main' application, written in VB6, needs to make a call to this assembly. So I create the TLB file, so its COM callable.
Now for deployment, is it better practice to place the managed assembly 'with' the tlb in the windows system directory? to have them both in the same place? Seems to me a bit easier to manage that way.
Or the managed assembly (not-signed since it isn't to be shared among diff apps) should just go to the BIN of the application dir, and the TLB moved to the windows\system32 and registered there.
Overall it seems more straight forward to keep them together, but it doesn't seem to be the correct way to do things.
Thx for any tips.

None of the above. You only need the type library when you compile your VB6 program. It does not need to and should not be deployed on the user's machine. There's a small corner case where a type library can help with marshaling an interface across an apartment or process. That won't be the case in a VB6 app.

Personally, I'd put both of them in your application's installation folder or under the Common Files structure.
The System32 folders are ideally just for the system files. (Ignoring history for the moment :)

Related

Determine which DLL and/or OCX files are actually used by my program?

My software is written in VB6. For diagnostic purposes I need to determine the actual DLL / OCX files which are loaded and used by the application on a customer's computer.
Since VB6 DLLs (including OCX files) are COM libraries they are loaded indirectly based on information in the registry. This means it is possible that a different file is being used than what was used in development / testing environments. Sometimes in a client environment this can cause malfunctions which are hard to diagnose without this information.
(My plan is to build a diagnostic readout window in my program that shows the libraries that the program is using at that moment.)
You can use the Dependency Walker to find which DLL your program depend on.
But the OCX are not so easy to find because they are loaded at run-time based on the application dependencies and the registered components through the Windows registry. But you have to already know which OCX components your application references - from the Tools > References and all the places you call CreateObject.
There are many ways in which runtime dependencies on DLLs (or OCX files) can be established. Ideally you would need to account for all of them:
This answer is specific to VB6 but many other programming languages would work similarly.
Mechanisms which establish runtime dependencies:
At Compile time for traditional dynamically-linked libraries (DLLs which are not COM)
Files are (as their name suggests) dynamically loaded at runtime based on the linking process done at the end of compilation
This includes VB6 code which has used a statement like: Declare Function … Lib …
(In .NET this would mean calling out into “native code”)
To identify: Inspect the source code.
To identify without sources: These can be detected by a tool like Dependency Walker
At Compile time for COM DLLs
In VB6 this is known as “early binding”.
This includes VB6 code which has explicitly set a reference to a DLL or OCX.
Note that the dependency is actually on the COM class or interface GUID, and not explicitly on the DLL file itself.
To identify: These are listed in the project VBP.
To identify (alternate): If you don't have the VBP or source code, these dependencies can generally be revealed by by IMPORT statements in OLEView. You might need to look up some GUIDs from there in the registry to see what actual DLL files are used.
At Compile time for statically-linked libraries (not COM, not DLLs)
Library code is included in the EXE or DLL which is being compiled. Therefore there is no runtime dependency to anything external.
As far as I am aware, this is not possible for VB6 programs. Something like a C linker could use libraries like this. A rough equivalent in .NET would be using ILMerge to combine assemblies.
At Runtime for traditional DLLs (not COM)
DLLs can be loaded arbitrarily using Win32 API such as LoadLibrary().
To identify: You have to look at the source to know what might happen.
Alternately if you don't have the source you could use tools like Process Explorer and/or Process Monitor to observe a running instance and see what DLLs actually get loaded.
At Runtime for COM DLLs
Classes can be loaded arbitrarily using eg VB6 CreateObject() calls.
In VB6 this is known as “late binding”
Which DLL will be used to provide the class will be determined by the process’s activation context. The activation context is established by the app manifest file (if there is one) or the Windows registry otherwise (the normal default for VB6 programs).
To identify: You have to look at the source to know what might happen. You also need to know what the configuration state will be on the PC that runs the code - which DLL files are registered, assuming a manifest is not used.
Alternative for no source code: as in the case above
Important: dependencies can be chained. So really you need to "walk the links" of all the dependencies until you build up a complete mapping of what is required. Somewhere in that mapping you can draw a line between what you need to deploy and what the operating system or other runtime environment can be relied on to provide. (IMO for VB6, that line should be drawn rather liberally).
You may be thinking that all this makes the task very difficult or tedious – I totally agree. :)

How to force creation of manifest file in release folder?

This is driving me crazy. I have developed a .NET COM DLL that is used by a VB6 DLL wrapper in order to update and replace some legacy functions in an application.
I am now trying to remove the requirement to use regasm on client machines so have worked out how to do that on a test DLL which all works fine.
I branched the DLL just in case and added an app.manifest file. Everything else worked out fine and I got it all working. The manifest is embedded and Visual Studio 2012 generates a mydll.dll.manifest file in the release folder.
Then I went back to the original trunk and added an app.manifest file (no point in merging as there were no code changes). I copied the contents of the branch into the app.manifest file and built the release version. The manifest is embedded in the DLL but no mydll.dll.manifest file is generated.
I know that it's not strictly necessary to have the mydll.dll.manifest file but I'd like things to be consistent (and for some reason the test process doesn't produce the same results with the trunk version) so how can I force it to be created?
This is a VB.NET DLL project so it doesn't have (or I can't find) the 'Generate Manifest' property drop down mentioned in the first answer here. How can I set this? Or is there a way to set it by editing the project file directly?
References:
Original walkthrough article and some corrections.
Overview by Junfeng Zhang in two articles plus a useful tool
You are making a fairly common mistake. A reg-free COM manifest helps an application find a COM server without looking in the registry to locate the DLL. Embedding the manifest in the DLL is like trying to solve the chicken and egg problem, Windows cannot possibly find that manifest if it cannot locate the DLL first.
The manifest needs to be part of the client app. Which is tricky since it is VB6, it doesn't support embedding manifests in its executables.
You could tinker with the mt.exe tool, an SDK utility that supports embedding manifests in an executable. You'd have to run it by hand after building the VB6 binaries. That's unfun and very likely to cause trouble when you forget. It is in general not a joyful tool to use, documentation is meager, incomplete and unhelpful, a chronic problem with manifests.
The fall back is a separate app.exe.manifest file, what Windows will look for next when it cannot find a manifest embedded in the executable. Where "app.exe" must be renamed to the name of the VB6 program. The EXE, not the DLL. This now also gives you a chance to avoid having to register the VB6 DLL, presumably what you really want if you truly want to make your program run reg-free. The disadvantage is that it will not work when you debug your VB6 program, wrong EXE. You'd also need a vb6.exe.manifest, located in the VB6 install directory.
Needless to say perhaps, very hard to get ahead with VB6 here. It just wasn't made to help you do this, they didn't have a time machine in 1998.
I have to admit that I don't know VB at all, but in the case of C++ and C# Visual Studio projects I previously had to resort to calling mt.exe in a post-build step in order to get the DLL manifest I wanted. Maybe that workaround would work in your case as well?

Can I package and utilize a dll with an MFC ActiveX Control Object?

I've been able to create a signed CAB file for web deployment containing my control and dll, but my control seems unable to access classes and functions in my dll even though it is listed as a dependency in the CAB's inf file. For all my research, I can't even tell if what I'm trying to do is "allowed". Followup: if it is possible to talk to a non-com dll, is it a security risk?
I'm using msvc 2010. Thanks for your time!
Pretty certain what I was trying to do wasn't possible. Ended up creating a class library instead so that I could reference and include the functions I needed at compile time.

Registration free COM: VB6 Executable referencing VB6 DLL

So, I've got a single VB6 executable that references multiple VB6 COM DLLs. Is it possible for me to generate, on-the-fly, a manifest for the executable as well as a manifest for each of the referenced DLLs? If so, then how?
I would like to perform this operation as part of our build process without having to register the COM DLLs as part of the process.
NOTE: All the reg-free COM examples that I've found so far involve .NET interop, which is not a requirement for what I'm doing.
[EDIT]
After performing some preliminary testing using Unattended Make My Manifest, I've found that its just not as user-friendly as I would like. And, since there's only a Sample.ini file for documentation I've had a pretty hard time understanding what should be put into that file compared to what doesn't need to go into that file. Anyways, I've decided to craft manifests using my own tool. Hopefully, I'll get permission from my employers to release the code as open source.
*For now, if you're in the same position that I'm in and you would like to create a build and production environment that uses side-by-side/registration-free COM interactions, just know that its possible. I would recommend crafting them by hand with a simple DLL and consumer app at first, and then incrementally building on that until it suites your specific needs.**
We are using Unattended Make My Manifest in daily builds to create portable versions. It creates a single manifest that can be embedded to the executable with mt.exe
You could try Make my manifest which is a tool to create the manifest for a VB6 program. I don't know whether it can run automatically as part of a build process.

Invoking .Net COM assembly from Powerbuilder application (without registration)

We have a Powerbuilder 10 application that is using .Net COM assemblies. We are trying to embed the manifest in the PB application (to invoke COM assemblies without registration). The merged manifest file has added sections for dependecies on the .Net COM assemblies. We have tries various tools to inject the new manifest with different results
- using GenMan32 to inject truncates the application from 6MB to 45KB.
- using ResourceTuner, the file size looks okay, but trying to launch application gives "Fatal Disk Error".
Any suggestions on invoked .Net ComEnabled assembly from PB without registration?
Have you tried it with an external manifest and ensured that works? If an external manifest doesn't work, then the manifest information isn't correct.
Once you have a valid external manifest, you might try the Manifest Tool (MT.EXE) from the .Net SDK. It works well with true EXE files. As Terry noted though, the PB generated executable contains additional information that tools that manipulate the EXE need to respect or they will break it.
http://blogs.msdn.com/patricka/archive/2009/12/09/answers-to-several-application-manifest-mysteries-and-questions.aspx
This is more a redirection than an answer. One thing you need to be aware of is that PowerBuilder produces executables that do not follow standards for Windows executable files. Essentially they are a bootstrap routine to load the PowerBuilder virtual machine, plus a collection of class definitions (objects). The cases you've brought up are not the first I've heard of where utilities meant to modify executables don't work on PowerBuilder executables.
As for a positive contribution on what other directions to follow, I don't really know enough to give qualified advice. If it were me, I'd try to register the COM object if ConnectToNewObject() fails, but I've got no idea if that possible or if that route is a dead end.
Good luck,
Terry.