|
-
Sep 29th, 2010, 12:04 AM
#1
Thread Starter
Lively Member
[RESOLVED] Big problem with manifest/UserControl combination
Hello folks, I was facing problems with my VB6 projects lately: they often crashed after closing the application (wanted to send crash information to Microsoft).
I made several tests and figured out, that this only happens, when I use a manifest (it doesn't matter if it is a separate file or in a resource file) AND a noncompiled UserControl (even if it has no single line of code!).
Even an empty project, which only initializes the common controls shows that behavior.
I did try it with both APIs:
Code:
Private Declare Sub InitCommonControls Lib "comctl32" ()
Private Declare Function InitCommonControlsEx Lib "comctl32.dll" (ByRef TLPINITCOMMONCONTROLSEX As InitCommonControlsEx) As Long
Interesting is also the fact, that the crashes do not happen on my system (VB6 installed, uxtheme.dll patched), but on other XP systems.
It also seems, that the crashes happen on Vista, but not on 7...
Can somebody help me??
Last edited by NeedHelp!; Sep 29th, 2010 at 12:09 AM.
-
Sep 29th, 2010, 08:49 AM
#2
Re: Big problem with manifest/UserControl combination
-
Sep 29th, 2010, 10:42 PM
#3
Re: Big problem with manifest/UserControl combination
The recommended solution is loaded into memory Shell32.dll.
Code:
Private Declare Sub InitCommonControls Lib "comctl32.dll" ()
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" ( _
ByVal lpLibFileName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
ByVal hLibModule As Long) As Long
Private m_hMod As Long
Private Sub Form_Initialize()
m_hMod = LoadLibrary("shell32.dll")
InitCommonControls
End Sub
Private Sub Form_Unload(Cancel As Integer)
FreeLibrary m_hMod
End Sub
Mr. Lavolpe've seen often in his project uses InitCommonControlsEx.
It is more convenient to use InitCommonControlsEx than InitCommonControls?
Last edited by LeandroA; Sep 29th, 2010 at 10:47 PM.
-
Sep 30th, 2010, 10:46 AM
#4
Re: Big problem with manifest/UserControl combination
I haven't found the need to load Shell32.dll in my programs, but perhaps that's because I call InitCommonControlsEx() before loading the first Form.
MSDN Library states:
InitCommonControls Function
Registers and initializes certain common control window classes. This function is obsolete. New applications should use the InitCommonControlsEx function.
And also:
Under Comctl32.dll version 6.0 and later, InitCommonControls does nothing. Applications must explicitly register all common controls through InitCommonControlsEx.
However: the call itself may do enough by causing the desired version of the library to be loaded.
-
Sep 30th, 2010, 03:58 PM
#5
Thread Starter
Lively Member
Re: Big problem with manifest/UserControl combination
 Originally Posted by dilettante
I haven't found the need to load Shell32.dll in my programs, but perhaps that's because I call InitCommonControlsEx() before loading the first Form.
No, I did use InitCommonControlsEx() before loading the first Form - and I still got the error in some cases.
LeandroAs tip did solve my problem and therefore help me a lot!
-
Sep 30th, 2010, 04:00 PM
#6
Re: Big problem with manifest/UserControl combination
Where did you call InitCommonControlsEx? Was it in Sub Main with project starting at Sub Main, or during Form_Load/Form_Initialize?
Like Dilettante, never had issues when starting it in Sub Main
-
Oct 2nd, 2010, 09:30 AM
#7
Thread Starter
Lively Member
Re: Big problem with manifest/UserControl combination
 Originally Posted by LaVolpe
Where did you call InitCommonControlsEx? Was it in Sub Main with project starting at Sub Main, or during Form_Load/Form_Initialize?
Yes, I did call it in sub Main with project starting at this sub.
 Originally Posted by LaVolpe
Like Dilettante, never had issues when starting it in Sub Main
Did you try it on other systems?
I had no problems on my system as well - but they did occur on other systems.
-
Oct 2nd, 2010, 10:32 AM
#8
Re: Big problem with manifest/UserControl combination
I have code that lots of users run on different PCs, never had a report of this issue.
I'd like to see an explanation of what the "fix" is supposed to actually accomplish. The vbAccelerator article sheds zero light on this, and is also trying to call InitCommonControls from within a Form. The MS KB article was about this issue:
If you enable a Windows XP theme in Visual Basic 6.0, you may encounter unexpected behavior. For example, if you place option buttons on top of a Frame control and then enable a Windows XP theme or visual style, the option buttons on the Frame control appear as black blocks when you run the executable file.
The guy seems to be off chasing red herrings. He also admits he'd managed to trash his Windows installation.
It is hard to argue with success, however I see nothing so far that would compel me to bother doing this. More information would be helpful.
Make sure you are using VB6 SP6.
Last edited by dilettante; Oct 2nd, 2010 at 10:40 AM.
-
Oct 2nd, 2010, 10:55 AM
#9
Re: Big problem with manifest/UserControl combination
Doing some digging I found that I had seen this before, some years ago. The problem only occurred on XP, but it doesn't on Vista.
This old program was trying to call InitCommonControls inside the main Form. It was getting that crash on exit as described above.
I just tried this on XP again, and the program fails there whether I call InitCommonControls from the Form or from Sub Main. Interesting, there may be something here.
-
Oct 2nd, 2010, 12:03 PM
#10
Re: Big problem with manifest/UserControl combination
 Originally Posted by dilettante
...I just tried this on XP again, and the program fails there whether I call InitCommonControls from the Form or from Sub Main. Interesting, there may be something here.
If you don't mind posting a bit more... I'd like to replicate it too, but am unsure of which scenarios fail.
1) Does it fail calling the EX version of the API?
2) Does it fail calling either version when loaded from Sub Main? If so which version(s) failed
-
Oct 2nd, 2010, 12:19 PM
#11
Thread Starter
Lively Member
Re: Big problem with manifest/UserControl combination
 Originally Posted by LaVolpe
If you don't mind posting a bit more... I'd like to replicate it too, but am unsure of which scenarios fail.
1) Does it fail calling the EX version of the API?
2) Does it fail calling either version when loaded from Sub Main? If so which version(s) failed
Yes, the error occurs when using the EX version called from Sub Main.
The reason for this are specific versions of ComCtl32.DLL 6.0.
Please read following article for more information:
http://www.vbaccelerator.com/home/vb...wn/article.asp
-
Oct 2nd, 2010, 12:49 PM
#12
Re: [RESOLVED] Big problem with manifest/UserControl combination
Ahhhh, success -- failure!!!!
Yes, I managed to replicate the problem. For all, this is what I did so you can replicate it too
1) Create a new project
2) Add an existing compiled VB usercontrol or create a new usercontrol, compile it, then add it to your project.
3) Place one of those usercontrols on your form
4) Place a standard vb button on the form also
5) Use your favorite method to apply themes (manifest file or manifest res file) plus supporting initialization code (Sub Main for example)
6) Compile the project & run the exe. It may crash on exit.
Now, I use a a resource manifest by habit. I made the simple tweak before the call to InitCommonControlsEx within sub main and it did indeed fix the issue... Note that I did not intend to keep hMod around for life of project. Calling LoadLibrary, showing the form, then releasing hMod proved to also relieve that annoying "crash on exit" problem.
Code:
Public Sub Main()
Dim iccex As InitCommonControlsExStruct, hMod As Long
With iccex
.lngSize = LenB(iccex)
.lngICC = ICC_STANDARD_CLASSES ' vb intrinsic controls (buttons, textbox, etc)
End With
On Error Resume Next
hMod = LoadLibrary("shell32.dll")
InitCommonControlsEx iccex
If Err Then
InitCommonControls ' try Win9x version
Err.Clear
End If
On Error GoTo 0
Form1.Show
If hMod Then FreeLibrary hMod
End Sub
Now off to make a simple tweak to my Manifest Creator project.
Last edited by LaVolpe; Oct 2nd, 2010 at 01:50 PM.
Reason: updated steps
-
Oct 2nd, 2010, 02:18 PM
#13
Re: [RESOLVED] Big problem with manifest/UserControl combination
The vbAccelerator article is worthless, explaining nothing. It only gives yet another blind copy of the workaround, without any explanation whatsoever.
This can occur whether using InitCommonControls or InitCommonControlsEx.
-
Oct 2nd, 2010, 02:57 PM
#14
Re: [RESOLVED] Big problem with manifest/UserControl combination
It looks like almost anything that causes Shell32.dll to be loaded before calling InitCommonControls/Ex will do the trick. VB6 UserControls must try to load this library for some purpose, and it appears the sequence is critical. Almost any innocuous call works as well as explicit loading/unloading.
Examples that work:
Code:
Private Declare Sub InitCommonControls Lib "comctl32" ()
Public Sub InitCC6()
CreateObject "Shell.Application"
InitCommonControls
End Sub
Code:
Private Declare Sub InitCommonControls Lib "comctl32" ()
Private Declare Function DriveType Lib "shell32" (ByVal iDrive As Long) As Long
Public Sub InitCC6()
DriveType 0
InitCommonControls
End Sub
Just do this prior to loading the main Form.
Note that DriveType requires XP SP2, so it might not be the best candidate. IsUserAnAdmin might be better.
Last edited by dilettante; Oct 2nd, 2010 at 03:02 PM.
-
Oct 3rd, 2010, 01:42 PM
#15
Re: [RESOLVED] Big problem with manifest/UserControl combination
With winXP SP2
Project without custom user controls.
at Running the compiled porject it appeares this error:
"runtime Error 453
Can't find DLL entry point FreeLibraryA in kernel32.dll"
-
Oct 3rd, 2010, 02:05 PM
#16
Re: [RESOLVED] Big problem with manifest/UserControl combination
FreeLibrary() has no string parameters, so there are no A and W versions. Take off the "A" and it should work for you.
I still think it may be a lot less clunky to just call something like IsUserAnAdmin() instead of doing the Load/Free though:
FreeLibrary Function
Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference count reaches zero, the module is unloaded from the address space of the calling process and the handle is no longer valid.
So if you Load and then immediately Free during Sub Main() you're trhashing around excessively. If you defer the Free you have an extra handle to keep around and to deal with later.
Note that even using this "cause shell32.dll to be loaded first" approach InitCommonControls/Ex ahould be called prior to the main Form being loaded. I've had failures even when this is done from within Form_Initialize, let alone Form_Load.
-
Oct 3rd, 2010, 03:32 PM
#17
Re: [RESOLVED] Big problem with manifest/UserControl combination
 Originally Posted by dilettante
FreeLibrary() has no string parameters, so there are no A and W versions. Take off the "A" and it should work for you.
Hmmm, probably got that from me (mainfest creator project). Mistake and typo on my part. Apologize. Fixed the typo in that project
 Originally Posted by dilettante
... So if you Load and then immediately Free during Sub Main() you're trhashing around excessively
Don't agree, Sub Main is only called once. No need to cache the reference handle. To test if FreeLibrary() freed the only instance of the shell32, I let a test exe run for hours, closed it and no problems. From what I've seen in other places on the web, Shell32 creates a hook into the InitCommonControlsEx api, which may be a reason why Shell should be loaded into the process space beforehand. FreeLibrary when called in Sub Main(), must not set its ref count to zero else I'd expect crashes due to the hooking action mentioned earlier.
Last edited by LaVolpe; Oct 3rd, 2010 at 03:45 PM.
-
Oct 3rd, 2010, 04:08 PM
#18
Re: [RESOLVED] Big problem with manifest/UserControl combination
I'd guess that FreeLibrary is decrementing the reference count, but Windows probably has some latency in removing the library from the process space. Even if it didn't this particular library is very likely to be in memory anyway, so adding it back on the next "hit" will be cheap.
The only advantage I see in calling some innocuous function like IsUserAnAdmin is that you have a few lines less code. The cost of this call seems negligible, and only needs to be done once.
If you want to argue for Load/Free then you can skip calling InitCommonControls/Ex as well and Load/Free it too. Remember that VB6 is going to take care of initializing any of the necessary classes itself. This seems to work fine: tested on Win7, Vista, and XP.
I'm afraid we may have been cargo-culting by calling InitCommonControls/Ex for years!
The only purpose it seems to serve is to get the right version of the library loaded. What puzzles me is why a normal VB6 program doesn't just do this itself, and I can only conclude that it uses some tricky technique that causes the manifest to be bypassed.
-
Oct 3rd, 2010, 06:25 PM
#19
Re: [RESOLVED] Big problem with manifest/UserControl combination
 Originally Posted by dilettante
I'm afraid we may have been cargo-culting by calling InitCommonControls/Ex for years!
The only purpose it seems to serve is to get the right version of the library loaded. What puzzles me is why a normal VB6 program doesn't just do this itself, and I can only conclude that it uses some tricky technique that causes the manifest to be bypassed.
Maybe, maybe not. By calling it you can explicitly decide which classes also get initialized. Haven't tested whether calling it without the appropriate classes (i.e., just calling it with ICC_STANDARD_CLASSES) will indeed theme a v5 progressbar, listview, etc.
-
Oct 3rd, 2010, 08:00 PM
#20
Re: [RESOLVED] Big problem with manifest/UserControl combination
Works fine here without calling it at all, just loading it. Even cue banners work in TextBox controls (after setting them).
-
Oct 9th, 2010, 06:53 AM
#21
Thread Starter
Lively Member
Re: [RESOLVED] Big problem with manifest/UserControl combination
 Originally Posted by dilettante
If you defer the Free you have an extra handle to keep around and to deal with later.
No, this is not true - following code seems to work perfectly:
Code:
Option Explicit
Private Type InitCommonControlsExStruct
lngSize As Long
lngICC As Long
End Type
Private Declare Function InitCommonControlsEx Lib "comctl32.dll" (ByRef iccex As InitCommonControlsExStruct) As Boolean
Private Declare Sub InitCommonControls Lib "comctl32" ()
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
' constant descriptions:
' http://msdn.microsoft.com/en-us/library/bb775507%28VS.85%29.aspx
Private Const ICC_ANIMATE_CLASS As Long = &H80&
Private Const ICC_BAR_CLASSES As Long = &H4&
Private Const ICC_COOL_CLASSES As Long = &H400&
Private Const ICC_DATE_CLASSES As Long = &H100&
Private Const ICC_HOTKEY_CLASS As Long = &H40&
Private Const ICC_INTERNET_CLASSES As Long = &H800&
Private Const ICC_LINK_CLASS As Long = &H8000&
Private Const ICC_LISTVIEW_CLASSES As Long = &H1&
Private Const ICC_NATIVEFNTCTL_CLASS As Long = &H2000&
Private Const ICC_PAGESCROLLER_CLASS As Long = &H1000&
Private Const ICC_PROGRESS_CLASS As Long = &H20&
Private Const ICC_TAB_CLASSES As Long = &H8&
Private Const ICC_TREEVIEW_CLASSES As Long = &H2&
Private Const ICC_UPDOWN_CLASS As Long = &H10&
Private Const ICC_USEREX_CLASSES As Long = &H200&
Private Const ICC_STANDARD_CLASSES As Long = &H4000&
Private Const ICC_WIN95_CLASSES As Long = &HFF&
Private Const ICC_ALL_CLASSES As Long = &HFDFF& 'combination of all values above
Public Function InitCommonControlsVB() As Boolean
Dim ret As Boolean
Dim hMod As Long
Dim iccex As InitCommonControlsExStruct
With iccex
.lngSize = LenB(iccex)
.lngICC = ICC_USEREX_CLASSES
'.lngICC = ICC_STANDARD_CLASSES Or ICC_LISTVIEW_CLASSES
' if using Common Controls; add appropriate ICC_ constants for type of control you are using
' example if using CommonControls v5.0 Progress bar:
' .lngICC = ICC_STANDARD_CLASSES Or ICC_PROGRESS_CLASS
End With
hMod = LoadLibrary("shell32.dll")
ret = True
On Error Resume Next 'error? Requires IEv3 or above
Call InitCommonControlsEx(iccex)
If Err Then
Call Err.Clear
Call InitCommonControls 'try Win9x version
If Err Then
ret = False
Call Err.Clear
End If
End If
On Error GoTo 0 'Disables enabled error handler in the current procedure and resets it to Nothing
'... show your main form next (i.e., Form1.Show)
Call FreeLibrary(hMod)
InitCommonControlsVB = ret
'** Tip 1: Avoid using VB Frames when applying XP/Vista themes
' In place of VB Frames, use pictureboxes instead.
'** Tip 2: Avoid using Graphical Style property of buttons, checkboxes and option buttons
' Doing so will prevent them from being themed.
End Function
But you may add your improvements and post them here, if you like.
-
Oct 9th, 2010, 07:47 AM
#22
Re: [RESOLVED] Big problem with manifest/UserControl combination
You don't need that much code though. This takes care of all of it:
Code:
Private Declare Function IsUserAnAdmin Lib "shell32" () As Long
Private Declare Sub InitCommonControls Lib "comctl32" ()
Private Sub InitCommonControlsVB()
IsUserAnAdmin
InitCommonControls
End Sub
I haven't had any problems no matter what controls I use on Windows XP, Windows Vista, or Windows 7.
Yes the matter of checkboxes, etc. in frames still exists but I think we expect that by now.
-
Oct 9th, 2010, 11:17 AM
#23
Thread Starter
Lively Member
Re: [RESOLVED] Big problem with manifest/UserControl combination
 Originally Posted by dilettante
You don't need that much code though.
Yes, indeed - your code is really neat!
But why did Microsoft develp the newer InitCommonControlsEx API?
-
Oct 9th, 2010, 12:09 PM
#24
Re: [RESOLVED] Big problem with manifest/UserControl combination
I'm not sure if this will be helpful but http://tek-tips.com/viewthread.cfm?qid=1042416&page=2 suggests that a call to InitCommonControls(Ex) is not required at all if you '... invisibly add a single control from Windows Common Controls to the first form that is to be made visible.' Could it be that the explicit call into Shell32 which you seem to require could also be avoided by trying that.
-
Oct 9th, 2010, 12:38 PM
#25
Re: [RESOLVED] Big problem with manifest/UserControl combination
 Originally Posted by NeedHelp!
But why did Microsoft develp the newer InitCommonControlsEx API? 
Calling InitCommonControls only controls when and how the DLL gets selected and loaded. The function itself does nothing and returns these days. When you actually use VB controls they load the classes needed by themselves, calling InitCommonControlsEx or some devious (undocumented?) near-equivalent internally.
InitCommonControlsEx is needed explicitly in things like C/C++ code, to load the necessary control classes used there.
Last edited by dilettante; Oct 9th, 2010 at 12:43 PM.
-
Oct 9th, 2010, 12:42 PM
#26
Re: [RESOLVED] Big problem with manifest/UserControl combination
 Originally Posted by Magic Ink
I'm not sure if this will be helpful but http://tek-tips.com/viewthread.cfm?qid=1042416&page=2 suggests that a call to InitCommonControls(Ex) is not required at all if you '... invisibly add a single control from Windows Common Controls to the first form that is to be made visible.' Could it be that the explicit call into Shell32 which you seem to require could also be avoided by trying that.
You can get away with this in some programs, and as we've seen you can even get away with only calling InitCommonControls in some programs. "Getting away with it" even varies with the OS versions, and maybe even the OS Service pack level!
So you really want to do both of these things, and do them prior to the first Form loading (Sub Main).
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|