Within certain limitations it is possible to create a portable application using MMM. The main limitations are:
I do not know how to isolate the VB6 runtime components yet, so you must rely on host machines having versions that your applications will work with already installed.
An ActiveX EXE cannot be isolated, so if you require any of these you must actually register them - thus such applications cannot be portable.
DCOM servers also require registration.
Many system component libraries cannot be isolated, so you must avoid trying to do so and rely on the versions installed on the host machines (ADO, DAO, SHDOCVW.dll, IEFRAME.dll, MSMQ, Scripting, etc.).
So if your application falls within the limitations and your host OS is Windows XP (preferably SP2 or later) or beyond, you may well be able to use MMM to make it "portable" (i.e. run it from a USB Flash drive or something similar without installing it).
You normally end up with a folder structure something like:
MMM can embed the manifest, in which case you won't have the separate .manifest file. The items in the {dependencies folder} can be ActiveX/COM DLLs or they can include 3rd party "standard" DLLs you reference via Declare Function or an interface typelib.
MMM tries to scan your .VBP file to locate your application's root dependencies. For each of these it will also seek .DEP files to locate sub-dependencies (just like the PDW does). Any of these MMM can locate it will try to isolate via the manifest and include in the resulting "package" folder, except for those it has listed in MMM.ini as "Exclusions" (normally non-isolable or non-redistributable dependencies).
You can manually add additional dependencies you know about, or you can soft-exclude others you know you do not want to isolate as part of the package. "Manually adding" dependencies is most important for anything you late-bind to in your application. Typically this means most anything you (a.) don't have a reference to in your project and (b.) you use CreateObject() on.
It is possible to collapse the {app folder} (i.e. package) tree and put both the dependencies and the data into the main folder with your EXE. I do not recommend this for the dependencies, because there is the chance that your EXE will end up calling a component library's self-registration entrypoint.
Part of the process the VB6 runtime goes through in linking to an ActiveX library involves registering components in this way if they aren't already registered. One of the main things you want in a portable application is to avoid touching the host machine's registry. If the runtime can't find the library (i.e. in the app folder) it will not try to self-register it.
Long-winded, yes. I hope it answers a few questions though.
There is nothing extra required, since this uses capabilities built into Windows these days. To "install" such an application onto a USB storage device just copy the contents of the package (app) folder over to it.
P.S. - MMM is far from perfect and can't handle every case. It does nothing you couldn't do by hand, but I hope it saves people some of the time required in creating such manifests manually.
Next question:
I made the PDM and DEP files (took a minute, I never use VB's PD wizard ).
The PDM shows 4 files that are "Missing Dependency Information".
Two of the 4 where intentionally excluded by MMM, so no prob.
But the other two aren't in the exclude list.
They are uxtheme.dll and DILIB.DLL.
After using MMM, those two files are not mentioned in the manifest and were not included in the distribution folder.
I think uxtheme.dll is part of windows and is probably ok, but I know I'll need to include DILIB.DLL.
Before trying to make this app portable, I had tried just placing DILIB.DLL in the VB6 program's own folder, but it wouldn't work until I placed it in the system32 dir.
When I saw that it wasn't included in the manifest file, I tried using regsvr32 on it.
I got this error msg "DILIB.DLL was loaded, but the DllRegisterServer entry point was not found".
I got a similar msg when I tried regsvr32 with the uxtheme.dll.
So what needs to be done to make sure those dll's work?
Last edited by longwolf; Dec 13th, 2008 at 02:20 PM.
The uxtheme.dll is part of Windows and can't be isolated.
This dilib.dll appears to be a 3rd party DLL used in JPEG compression or something. Any standard DLLs of this kind can be added to the package in MMM from within the Dependencies panel (click on the Add button, add by File Location of the DLL on your development system).
I'd have to assume from the results of trying to register dilib.dll that it is a standard DLL you use via one or more Declare statements.
The uxtheme.dll is part of Windows and can't be isolated.
This dilib.dll appears to be a 3rd party DLL used in JPEG compression or something. Any standard DLLs of this kind can be added to the package in MMM from within the Dependencies panel (click on the Add button, add by File Location of the DLL on your development system).
I'd have to assume from the results of trying to register dilib.dll that it is a standard DLL you use via one or more Declare statements.
Yes, dilib.dll is used by Declaring it.
And I did try using the Add button.
dilib.dll still isn't mentioned in the manifest.
But you're saying it will work anyway?
And, going from your 1st post, it should be in a sub-folder below the program exe to prevent problems?
Hmm, if it was successfully "added" the manifest should end up with a one-line entry for it since it has no class or type info to include. I just tried one and that's what I got.
Yes, for best results I recommend choosing a dependencies folder (just call it DEPS or something). However it should not be required to do so at all.
Last edited by dilettante; Dec 13th, 2008 at 02:42 PM.
Got it, it was my mistake, I had added it in the non-code panel instead of the dependencies panel.
======
Question 3
After pointing MMM at my project file, I get this from MMM.
Code:
Library soft-excluded by MMM:
Library = MSComctlLib
Description = Microsoft Windows Common Controls 6.0 (SP6)
File location = ???????????????`
Typelib ID = {831FDD16-0C5C-11D2-A9FC-0000F8754DA1}
Version = 2.0
Source = "VBP"
I searched my comp for it but only found Interop.MSComctlLib.dll and Interop.MSComctlLib.dll.deploy from the RegFreeCOM.exe at: http://msdn.microsoft.com/en-us/magazine/cc188708.aspx
Can I just place a copy of them in MMM's DEP folder?
Or would this MMM Manifest Settings take care of it, the option to 'Include Common Controls 6.0 in manifest'.
The pop-up says 'You must insure that you call IniCommonControls() properly to avoid causing your program to fail to start.'
I have no idea what IniCommonControls is or how to call it.
That is actually MSCOMCTL.OCX and though it is named similarly it has nothing directly to do with "Common Controls 6.0" which relates to control themeing starting with Win XP.
The MMM log should show:
File location = C:\Windows\system32\MSCOMCTL.OCX
"Soft excluded" means you have unchecked the dependency in the grid of dependencies on the Dependencies panel. Perhaps this was just a "slip of the click" on your part?
The garbage text in File location makes me really wonder. It almost makes me think this component's registration is corrupt on your machine.
You did uncover a typo in MMM though, that dialog should have been mentioning InitCommonControls.
That is actually MSCOMCTL.OCX and though it is named similarly it has nothing directly to do with "Common Controls 6.0" which relates to control themeing starting with Win XP.
The MMM log should show:
File location = C:\Windows\system32\MSCOMCTL.OCX
Do you mean the manifest file? I don't see an MMM Log file.
The manifest does have 5 references to progid="MSComCtl2.
But nothing for MSCOMCTL.OCX
Originally Posted by dilettante
"Soft excluded" means you have unchecked the dependency in the grid of dependencies on the Dependencies panel. Perhaps this was just a "slip of the click" on your part?
Don't think so, I've run it several times.
I thought that maybe the Soft Exclude was caused by the corrupted file path.
Originally Posted by dilettante
The garbage text in File location makes me really wonder. It almost makes me think this component's registration is corrupt on your machine.
The only other way for a dependency to be soft-excluded is for it to be found in the .VBP or a .DEP file but not found on the system where the .VBP or .DEP files say it is.
Have you tried opening the project in the VB6 IDE, then removing the Component reference and adding it back? Could you try posting a ZIPped copy of just your .VBP file?
Something is broken. I tried MMM on a small project using this Component library and everything works fine here.
Truthfully it looks like there is something wrong with the way MSCOMCTL.OCX is registered. You might try to unregister/reregister it using regsvr32:
Open a command prompt.
CD c:\windows/system32
regsvr32 /u MSCOMCTL.OCX
regsvr32 MSCOMCTL.OCX
I also notice you are early-binding to ADOX. This will almost certainly fail if you ever try to run your program on Vista, etc. There is no ADOX 2.8 there, only ADOX 6.0, and unlike for ADO there are no compatability typelibs present.
The only fix is to remove the ADOX reference, change all ADOX object variables to AS Object, and use Set X = CreateObject("ADOX.class") instead.
Well, no luck
I unregistered/re-registered MSCOMCTL.OCX, Closed/reopened the VB IDE, re-ran the P&D and then re-ran MMM.
MMM is still showing the corrupted file path.
Looking at the old and the new PDM files, they both show a good path:
C:\WINDOWS\system32\mscomctl.ocx=Yes
I searched the registry for object reference from the vbp "{831FDD16-0C5C-11D2-A9FC-0000F8754DA1}" and it shows: C:\WINDOWS\system32\mscomctl.oca
I tried the whole thing using a test project on two other computers with VB6 on them, compiling from scratch and then running MMM. They all work fine.
Here's one wild idea:
MMM comes with its own copy of MSCOMCTL.OCX (version 6.1.97.86) so try swapping that in, at least temporarily.
Open the DEPS folder in the MMM folder. Then open C:\Windows\System32 and rename your existing MSCOMTCL.OCX to MSCOMCTL.SAV. Then CTRL-drag (or copy, paste) the MSCOMCTL.OCX from DEPS to System32. Then do the unreg & reg as above.
Then go back and try running MMM with your project once more.
Worst comes to worst, go back into System32 and delete the (new) MSCOMTCL.OCX and rename MSCONCTL.SAV back to MSCOMCTL.OCX.
One other consideration with reg-free COM: Microsoft changed the controls and runtime to work better with reg-free COM in VB6 SP6. Some pre-SP6 controls will work in some situations, but not all. The changes only take effect on XP SP2 or later OSs.
I un-registered the old MSCOMCTL, swapped in your newer MSCOMCTL.OCX and got it registered, deleted the PD and MMM files and restarted the VB IDE.
While re-running the PD wizard I got this msg,
'The wizard found dependence information for the listed files, but the information is out of date. To proceed with the out of date information, click OK'.
It was indicating the MSCOMCTL.OCX file.
Tried MMM, no go.
Checked the vbp and registry, the Typelib ID hasn't changed even thou your version is newer.
But the text case did change, mine was all lower case.
Made a temp vb project, added MS Common Controls 6 (sp6), i.e. MSCOMCTL.OCX
Cut all of the dependent controls from the main project (18 forms worth) and pasted them into the temp project.
Removed MSCOMCTL.OCX from the main project, saved it and closed the IDE.
Re-opened it, and put everything back.
Recompiled, ran PDW.
Got the same PDW msg.
Tried MMM anyway, no joy.
Rebooted and tried the PDW again, still got the out of date msg.
Checked the help file, it mentioned the MSCOMCTL.DEP file.
Checked the DEP in notepad and the version didn't match the new MSCOMCTL.OCX version.
Backed up the MSCOMCTL.DEP, changed the version numbers and saved it.
That fixed the PDW msg.
But MMM still couldn't get the path.
So, in the MMM 'dependencies to isolate' panel, I removed the bad, unchecked MsComctlLib entry.
Then manually re-added it.
Yes, the PDW is designed to complain when the date/version info in a .DEP file does not match the actual values of the associated .DLL/.OCX file. In such a case you can tell PDW to ignore the "out of date" info when you understand what you have done.
It is interesting that removing the automatic (but excluded) entry and then adding a manual entry did the trick. That seems very peculiar and might provide a clue. I didn't suggest trying that because both processes use the same procedure to look up ClassIds, ProgIds, file locations, etc.
Very interesting... they can't be identical because one begins with info from the .VBP and the other with a ProgId or path to the library file. Hmm. A corrupted name in a .DEP could lead MMM astray too of course but I don't see that as the source of this problem here.
The good news is you got someplace.
The ADOX changes should be simple. As I said, remove the project's ADOX reference (optional) and then change all ADOX objects you declare to As Object and then make sure you create them using CreateObject() instead of using the New keyword.
No, you're safe as far as ADO itself (ADODB) goes. For a very long time now (starting at ADO 2.1) Microsoft has been providing compatability typelibs. For example with Vista even though it has ADODB 6.0 it includes typelibs that point your program to the 6.0 version even if you referenced the 2.8, 2.7, 2.6, 2.5, 2.1, or 2.0 interfaces.
Some people think they have "multiple ADOs" installed but they don't - and if they do they shouldn't!
This is why most portable applications should reference ADO 2.5 unless they require features added in ADO 2.6 or later. You program will actually use the version of ADO the host system has installed via ADO 2.5 interfaces and will be limited to the ADO 2.5 feature set (in most programs not a problem).
Since you need XP or later anyway, ADO 2.7 is a safe lower limit since Windows XP Gold (initial retail release) had ADO 2.7 as part of the OS.
So...
You only need to late-bind the ADOX objects you use, and only because Microsoft did not handle ADOX interface versioning the same way it did ADODB.
The late binding you need is simple. Where you declare or create ADOX objects just change things like:
Code:
Dim catDB As ADOX.Catalog
Set catDB = New ADOX.Catalog
... to:
Code:
Dim catDB As Object
Set catDB = CreateObject("ADOX.Catalog")
The same goes for any other ADOX objects (Table, Column, etc.): just declare them all As Object.
1. Late Bound the ADOX controls.
2. Removed the ADOX reference.
3. Lowered the ADODB version to 2.5
4. Tested the app, all's good
5. Saved and recompiled
6. Ran PDW
7. Ran MMM, added DILIB.DLL, fixed the MSCOMCTL.OCX ref. and had MMM place them in a DEP folder.
8. Copied the MMMPack folder to a thumb drive and tried it on my room mates WinXP comp.
It accessed the DB without a problem.
But crashed when I had it call DILIB.DLL.
It gave the error 'DILIB.DLL not found'
Ran MMM again without making the DEP folder, all the files were placed in with the EXE.
Still crashed with the same error
The manifest does have the ref
Code:
'with the DEP folder
<file name="DILIB.DLL" loadFrom="DEP\DILIB.DLL">
'without the DEP folder
<file name="DILIB.DLL" loadFrom="DILIB.DLL">
I edited/complied it and set up for MMM.
Had to manually add Bmp2jpeg.dll, just like the DILIB.DLL.
Interestingly, comdlg32.ocx got the same corrupt file path as MSCOMCTL.OCX.
I fixed the path the same way and tested the MMPack on another comp that doesn't have Bmp2jpeg.dll.
It worked fine.
So I changed my project to the Bmp2jpeg.dll.
Did all the steps.
But I got the "Bmp2jpeg.dll not found" error when I tested it.
I copied my exe, vbp, dep, and pdm files along with the Bmp2jpeg.dll to a folder on my thumb drive.
Then copied MMM's folder to the drive and tried running it on another comp.
It seemed to go well, no file path problems.
But when I ran my exe i still got the missing dll error.
The .DEP and .PDM files are only used by the packager (P&DW), and MMM scans .DEP files too of course.
I had taken a look at that other Project that uses Bmp2jpeg.dll, did you say MMM works for it but not for your Project? That's what I was getting at. If one Project works and the other does not there must be something different between them. My guess is the Declare statements in your program.
What else it might be I can't guess. Clearly something is going on though.
I've never had anyone else report this problem. Are you sure you only use the "simple name" in your Declare statements? Just "Bmp2jpeg.dll" with no path?
The .DEP and .PDM files are only used by the packager (P&DW), and MMM scans .DEP files too of course.
I was just making sure I didn't have to run across the house a dozen times
Originally Posted by dilettante
I had taken a look at that other Project that uses Bmp2jpeg.dll, did you say MMM works for it but not for your Project? That's what I was getting at. If one Project works and the other does not there must be something different between them. My guess is the Declare statements in your program.
Yes, I took his project, REMed the section that checks the system folder, complied it, etc.
That project worked fine.
Originally Posted by dilettante
I've never had anyone else report this problem. Are you sure you only use the "simple name" in your Declare statements? Just "Bmp2jpeg.dll" with no path?
I'm lazy, I just did a copy and paste on the declaration.
Code:
Private Declare Function BmpToJpeg Lib "Bmp2Jpeg.dll" (ByVal bmpFileName As String, ByVal JpegFilename As String, ByVal CompressQuality As Integer) As Integer
'the bmp project used it like this:
If BmpToJpeg(txtBmpfile.Text, txtJpgfile.Text, Val(cboQuality.Text)) = 0 Then
MsgBox "Can't make JPEG file", vbCritical, "Err"
Else
MsgBox "Successfully jpeg created.", vbApplicationModal + vbInformation
End If
'I used it like this:
If BmpToJpeg(sBmpPath, sJpgPath, 90) = 0 Then
frmMsgBox.Msg "There was a problem converting the photo." & vbCrLf & sMsg, _
, "Photo Error", mbExclamation
Kill sBmpPath
Exit Function
End If
After my app failed, it tried something on the manifest file.
I moved the dll call to the top of the list, above the two ocx's.
There was no error about the dll, instead I then got errors about the ocx elements (datepicker, etc)
Last edited by longwolf; Dec 16th, 2008 at 07:32 PM.
Ok, I gave up and did away with any of the jpg dll's.
MMM seems to have done a fine job once they were gone.
I've got a few questions left about the final MMM Manifest Settings.
1. 'Include Common Controls 6.0 Manifest'
Is this only needed if you want to apply XP Themes to the vb6 controls?
2. 'Include VB 6.0 KB 828629 remediation'
a. I've read the KB, but don't understand it. Is it saying there's a problem with VB6 made ActiveX controls, or does it apply to things like MSCOMCTL.OCX
b. It says that VB6 SP6 and WinXP SP2 are required. Does that apply only to the development machine?
3. 'Include trustInfo node in manifest'
I have no idea what trust level my app would need on Vista. It makes, copies and deletes files within it's own folder.
I've got one beta tester for my app, and I've already scared him.
He didn't tell me he was running Vista and I sent him a InoSetup file that didn't make it through the install
I don't have a Vista machine to test on and I don't want to scare him off by having a second glitch before he even gets to see the app
Ok, I gave up and did away with any of the jpg dll's.
MMM seems to have done a fine job once they were gone.
Sorry, I hope we can iron things like this out in the future but so far I can't reproduce this or the corrupted OCX file location problem.
I've got a few questions left about the final MMM Manifest Settings.
1. 'Include Common Controls 6.0 Manifest'
Is this only needed if you want to apply XP Themes to the vb6 controls?
Yes. And this also applies to Vista, Windows 7, etc. Themes are just part of the "user experience" these days. Note that you'll need to properly initialize the underlying comctl32.dll to avoid your program failing during initialization if you select this option. There are lots of articles about using XP styles though.
2. 'Include VB 6.0 KB 828629 remediation'
a. I've read the KB, but don't understand it. Is it saying there's a problem with VB6 made ActiveX controls, or does it apply to things like MSCOMCTL.OCX
b. It says that VB6 SP6 and WinXP SP2 are required. Does that apply only to the development machine?
It is saying that Reg-Free COM/SxS Isolation was not properly implemented for ActiveX controls in Windows XP and XP SP1. They took care of more issues in XP SP2 but the manifest needs additional entries now and the VB6 SP6a runtime (or later) is needed to fully take advantage of the changes.
Not every control or every program is impacted, so if you test on XP SP1 and your program works fine, great. However w/o testing you will not know whether your program requires the remediation or not.
XP SP3 includes a VB6 runtime later than SP6a.
3. 'Include trustInfo node in manifest'
I have no idea what trust level my app would need on Vista. It makes, copies and deletes files within it's own folder.
I've got one beta tester for my app, and I've already scared him.
He didn't tell me he was running Vista and I sent him a InoSetup file that didn't make it through the install
I don't have a Vista machine to test on and I don't want to scare him off by having a second glitch before he even gets to see the app
If your program does not require admin rights you use trustInfo set to asInvoker. If the program must run as admin set it to requireAdministrator, and will always prompt for elevation.
The highestAvailable setting uses whatever the user has inherently, always prompting for elevation if an admin user runs the program. The program is expected to sense whether it is running elevated before trying to do anything requiring admin permission.
Leave uiAccess = False. Using True requires that your application be cryptographically signed anyway.
People here hate to hear it, but XP's days are numbered. We still need to support it but if the user isn't at SP2 or 3 they have bigger problems. It is getting very late in the day to catch up on Vista development, and there are numerous small issues to deal with. Many of those are spelled out in a FAQ here.
Windows 7 is just around the corner. I suspect we'll see it released before the end of 2009.
And of course using VB6 to create portable applications is pushing the envelope a bit anyway.