|
|
Subject:
Problem: get error 429 when running a COM dll across a network
Category: Computers > Programming Asked by: plucktick-ga List Price: $130.00 |
Posted:
01 Mar 2005 06:30 PST
Expires: 31 Mar 2005 06:30 PST Question ID: 482849 |
We have a software application written with an Excel XP front end with VBA that calls COM (Component Object Model) dlls written in either Microsoft Visual Basic 6 or Visual C++ 6 ATL (Active Template Library). It works fine when the dlls are installed and registered on the user's local pc, but at run time we get "error 429: ActiveX cannot create object" when running from the local pc with the Excel front end file and dlls installed across a local area network on a Windows 2000 server. The error message typically occurs on a line of VBA code where we actually try and instantiate a COM object, e.g. Dim objMyObject as CMyObject ' where CMyObject is a class defined in a COM dll registered on the server set objMyObject = new CMyObject ' the error occurs on this line Such lines seem to work with some of simpler Visual Basic dlls (e.g. we have one which just wraps the standard VB Dictionary class to produce an improved dictionary class), but fail with either our Visual C++ ATL COM dlls (which are typically more complicated, with structures defined in their IDL [Interface Definition Langage] files), or our VB dlls which implement COM interfaces defined in one of our C++ dlls. Other information (which may or may not be relevant): I don't know what other information you might need, but the VB dlls are apartment threaded, and the C++ dlls are dual and support ISupportErrorInfo. We haven't consciously set any special settings for anything unusual, such as multiple threads (the dlls don't create any extra threads), or marshalling. What can we do to solve this problem which is currently preventing us from installing the software for multiple users on a network server, as opposed to installing it on all pcs? Thanks | |
| |
|
|
There is no answer at this time. |
|
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: areeew-ga on 01 Mar 2005 07:33 PST |
Can I get a free question? :-) How does one become a Google Researcher, a Freelance Answerer? Thx much! Areeew |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: mathtalk-ga on 01 Mar 2005 09:19 PST |
If your interfaces involve "complex" datatypes, then not only is the "automation" interface not available, you will probably need to write custom marshalling code to get the interfaces to work across process boundaries. When a COM interface is implemented in a DLL and called from a program on the PC where it is installed, the interface is most likely being invoked within a single process. When the component resides on a remote machine, Microsoft's DCOM (Distributed COM) takes advantage of "proxy/stub" processes on the calling and on the remote machines to facilitate the invocation. However the component needs to be written in a way that supports calls across process boundaries. If you cannot limit the necessary interfaces to those "simple" datatypes supported by the automation interfaces, then this points to a need to do your own "marshalling" (mapping complex datatypes, possibly including pointers, across process boundaries; pointers only have an "absolute" meaning within a process's address space, so that threads of one process can easily share pointers but separate processes require interception to create the illusion of sharing). regards, mathtalk-ga |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: frde-ga on 01 Mar 2005 13:03 PST |
Am I right in saying that you have :- An Excel front end - A bunch of AX DLLs that use other AX DLLs - and all these DLLs are on the server - You have copied your App to a server drive - and now try to run it off the server drive An AX DLL is a horrible thing, you give VB its internal name, VB then translates that into a supposedly unique 64 byte string and pokes around in its LOCAL registry for the physical file location. (well that is the early binding version, and late binding is still pretty nasty) The point is that the DLL only exists if it is known in the Registry. It might be sitting there in full view, but AX will not see it. On each machine you need to run RegSvr32 xxxxx.dll for every DLL for the local Registry to see it. There are ways of automating it. If I have misinterpreted what you are trying to do, then apologies. |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: plucktick-ga on 02 Mar 2005 06:21 PST |
Mathtalk and frde - thank you for your comments. In reply and clarification: mathtalk: if I need to write custom marshalling, how do we do this for a) VB6 Active X dlls, and b) VC6 ATL COM dlls? I have books "Inside Distributed COM" (Guy Eddon, Henry Eddon, Microsoft Press 1998) and "Essential COM" (Don Box, 1998, Addison Wesley) but have not found it easy to extract/understand the relevant bits from these books. frde: you are correct, everything is installed on the server (that is the point of trying to install over the network: only one location to install on, updates are easier to install, file access control is easier to administer). You say that active X dlls are "horrible things", what alternatives are you proposing? (We may well need to rewrite some of the active x dlls in .NET in the future, but we want to avoid that if it is unnecessary, and also, some of these dlls were written in 1998, well before .NET came along). I appreciate what you are saying about the need for the operating machine to find the COM dlls, but in fact that wasn't the problem we experienced: the Excel VBA project on the server when opened by a pc on the network will still compile (indicating that the VBA project references are fine, and the operating system can find the COM dlls), we just get a runtime error when trying to create certain objects. In fact, it is not clear to me which "complex" datatypes are likely to cause problems such as the error 429, is it simply anything other than the base types ([boolean, byte, small, short, long, hyper, float, double, char, wchar_t, enum, Interface Pointer in IDL], [unsigned char, char, short, long, __int64, float, double, wchar_t, enum, Interface Pointer in Microsoft C++], [Integer, Long, Single, Double, Enum, Interface Reference in Microsoft VB]) or Extended Types ([VARIANT, BSTR, VARIANT_BOOL in IDL], [VARIANT, BSTR, short in MS C++] and [Variant, String, Boolean in MS VB])? For example, if I define a struct in IDL and use that as a parameter in a C++ ATL COM dll, is that likely to cause an error 429? If so, what do I need to do to correct this, ideally without having to completely rewrite the original dll and all dlls that use it? (Presumably, if structs cause problems but Interface Pointers don't, then replacing the structs with equivalent Interface Pointers would work, but this would cause a lot of work, and seems over the top when the whole point of a struct is to provide a simple data storage variable for a variety of basic types. |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: plucktick-ga on 02 Mar 2005 06:35 PST |
Areeew: someone has probably already told you this, but basically the answer is RTFM: look at the Google Answers FAQs (http://answers.google.com/answers/faq.html) and more specifically the FAQs about Researchers (http://answers.google.com/answers/faq.html#aboutres). Regards |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: frde-ga on 03 Mar 2005 00:40 PST |
More on Error 429 - but this is probably not your problem - reason below. <quote> Symptom I When trying to site a control within your project, you receive the following error message: License Information For This Component Not Found. You Do Not Have An Appropriate License To Use This Functionality In The Design Environment. Symptom II When trying to compile your project, you receive the following error: Compile Error : Permission Denied Symptom III When trying to run your project, you receive the following error: Runtime Error '429' : ActiveX Component Can't Create Object </quote> http://support.microsoft.com/kb/q181854/ The above link is the MS fix for VB5 However just the same problem occurs in VB6 - there is also a VB6 fix - here you go http://support.microsoft.com/kb/194751/EN-US/ Watch out though - these look like SP6 - SP6 is hooky If your app was working fine on one machine, then you don't have marshalling problems, you don't have complex data type problems - all you have is something that comes up in the VB NGs about twice a week Just because you can 'compile' a VBA project in Excel does not mean that AX DLLs that use other AX DLLs can find those 'slave' DLLs Compiling in Excel will update your registry with what Excel knows about, but it will do nothing for things that Excel uses /indirectly/. If your App was working, but no longer works now you have moved it, then your problem is that VB/Windows (not Excel) does not know where to find something. And VB/Windows looks in the Registry even if the AX DLL is under its nose. Just to put your mind at rest, 'marshalling' is the jargon name for one AX EXE communicating with another one and sending/receiving data. - actually it is cross process communication - I call it passing data through the EXE blood brain barrier. I strongly suspect it is really just Windows messages with a lot of WM_COPYDATA which is the way one shunts data from one EXE to another. It is how AX EXEs work. (Oops - COM Client/Servers) Also with COM there are remarkably few data types. One needs to be a nutter to try passing structures, it expects the core VB data types and ... Objects. Definitely no UDTs (structures). I did not understand your last bit about RTFM on Google Answers - the researchers don't tend to answer a question unless they are darn sure - Hummer slightly missed your problem - I think he thought you were getting a failure /always/ - not after moving to a NW drive - Mathtalk thought you were using DCOM - I thought your problems were with the users machines - not on the changed dev machine With problems like this, in future I suggest a VB News Group - this is one that has some impressive people posting in it: microsoft.public.vb.general.discussion Also, GA commenters may or may not know what they are talking about, often they know precisely - but should hold off a bit to give the Researchers a crack. There are a few more things you should know. VB DLLs like all of VB are single threaded AX EXEs can be made to .. sort of .. have multiple threads, but what they really have is multiple data segments and their own internal threads. Your C++ DLLs are probably 'real' DLLs, not AX things, but they might talk out to AX - who knows. If your system was working on one drive, and now does not on another drive, then I am sure that it is a registry thing and you need to use RegSvr32 ... ah and for 'real' DLLs you had better make sure that they are in your Path ... if they are not found by an AX DLL you could have severe grief. |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: plucktick-ga on 04 Mar 2005 12:17 PST |
frde - thanks for your further comments. I think you may have hit the nail on the head when you say that the problem might be to do with dlls which are unregistered on the client machine being called by other dlls which are registered. By registering all the dlls (not just those which are used directly by Excel VBA) on the client machine, and by copying the "real" (in your terminology, I think you mean non COM, or non Active X) dlls from C:\WINDOWS\SYSTEM32 on the server into C:\WINDOWS\SYSTEM32 on the client machine, then our error 429's seem to have disappeared. However, I don't understand what you mean in some of your other comments: (1) I still don't see what alternatives you propose to ActiveX dlls, which we like because of the reasons already mentioned (Intellisense, self describing, reduces compile time errors ...), plus ability to call from various languages (e.g. c++, VB, VBA) (2) When you say "If your app was working fine on one machine, then you don't have marshalling problems, you don't have complex data type problems - all you have is something that comes up in the VB NGs about twice a week". I don't understand why the app working fine on one machine (with all dlls installed locally and hence working within the same process, in this case the process owned by Excel.exe) implies that we wouldn't have marshalling problems when we move to a situation where the dlls are on a different machine from the Excel exe? (3) It appears at the moment (from the fact that our app now seems to be working across a peer to peer network [we will test it soon on a client/server network], following the registration of all dlls on the client) that we don't seem to have marshalling problems, in spite of our using structures as parameters for some of our objects' methods. Any ideas why all the fuss is made about marshalling (i.e. long chapters in books), yet it doesn't seem to apply in a real live case? (Don't get me wrong, I'm very glad that we don't seem to be having problems, but am just puzzled as to why not, given what you and some others have said!) (4) you say "One needs to be a nutter to try passing structures, it expects the core VB data types and ... Objects. Definitely no UDTs (structures)." Strong language - I don't think we are nutters, yet we have successfully used c++/IDL structures in c++ COM dlls which seem to work fine with VBA and other c++ COM dlls. IDL seems to allow structs to be defined in IDL files, which would be odd if they weren't supposed to be used, also structs are useful in that they are quicker and easier to set up (when we want to pass a variety of data types in one parameter) than the alternative, which would be to create a COM Interface with property get/set for each data type we wanted to pass. A COM interface seems overkill when a struct seems to work just fine?! (5) you say "Your C++ DLLs are probably 'real' DLLs, not AX things, but they might talk out to AX - who knows." In fact, they are ActiveX dlls, produced using ATL (Active template library), ie. they are self registering, appear in the VB Object Browser once you have set a reference to them, show their methods in Intellisense etc. However, we do have 3 standard dlls (non self registering), which as mentioned above we do seem to have to put into a standard win32 path on the client for them to be found. So thanks for your comments re registry entries on the client pc, which seem indeed to have put us on the right path, although I'm a bit mystified by some of your other comments. Are you a Google researcher by the way? If so, I would accept your comments re the need for registry entries + how to automate this (e.g. via a script?) on several client pcs, plus a clarification of my queries re your other comments as an answer :) thanks and regards |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: frde-ga on 04 Mar 2005 18:38 PST |
@plucktick Glad to hear that you have got things running. You will, of course have similar problems on all the other machines - but since you have seen it through once, it will be less scary Right now I am rather brain dead, so I shall dissect your message and reply tomorrow - at length. I am not a GA Researcher, so ... well my thoughts are gratuit. I would be interested in knowing your VB skill level, just so that I can pitch the solution in a comprehensible manner. For others, the state of play is :- a) A VBA driven App with VB and non AX DLLs b) It is sitting on a simple shared drive c) Those darn DLLs need to be RegSvr32'd d) c) is not a problem but unregistering the earlier versions is - well sensible, or there will be shedloads of 'dead pointers' Basically a sort of nanny for AX de- and re-registration utility |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: plucktick-ga on 05 Mar 2005 01:36 PST |
hi frde - sorry to hear that you're not an officially accredited researcher, if GA won't make you one, perhaps we can sort something out via p a y p a l or other if you give me your details :) As for my VB skill level, I would say that it is advanced in most areas, but by no means all. I have been writing VB for 9 years now (initially VB4, but mostly VB6), from standard exes to Active X dlls and exes. I've never found much use for Active Documents and the other project types, but I have written a couple of ActiveX controls (ocx's) which have stood the test of time. I have written many COM interfaces and implemented them in VB6, I know how to write/read to/from the Registry, use APIs, how to communicate with c/c++ dlls (both standard and COM). I also know DAO, and some ADO for communicating with databases. On the other hand, if a topic is not mentioned here (e.g. VBScripts - which would presumably be one possibility for automating the registration process on client pcs), my knowledge level is probably very low. Hope that helps you frame your answer, many thanks and regards pluctick |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: frde-ga on 05 Mar 2005 06:37 PST |
Hi, No worry about the researcher bit. It sounds as if what I am going to suggest will be pretty easy for you. Also it might open some new vistas. The way I see it, your objective is to keep all the DLLs in one place. You have two problems. 1) Registering the AX DLLs 2) Getting access to the non-AX DLLs Let's tackle the second problem first. You don't really want to have to copy the non-AX DLLs to each machines windows\system32 directory - that requires administrator access and rather defeats the purpose of the exercize. The first thing to do, I think, is to check the App.Path. If it the same as your network directory, then you don't have a problem, and can simply put the non-AX DLLs in that directory. If it is not the same then one can 'fiddle' the PATH=c:\windows;c:\... line in the environment strings. On startup VB makes a copy of the environment strings, but using the APIs GetEnvironmentVariable and SetEnvironmentVariable one can change the environment strings, the change is not shown in the VB function Environ(), but it is recognised when VB goes hunting for DLLs. My hunch (and hope) is that this will not be necessary, and you simply need to stick the DLLs in the same path as the App on the network. Note: the Search path for DLLs is as follows: The directory containing the EXE The current path of the app CurDir The System Directory The Windows Directory The directories in the PATH: environment string Tackling the AX registration is more of a nuisance, you could simply shell out to a batch file and run RegSvr32 for each of the DLLs. RegSvr32 /s thething.dll runs it in silent mode However there is a sneaky way of registering DLLs and OCXes from VB using the API CallWindowProc. There is an excellent downloadable API Guide at http://www.mentalis.org/agnet/ You need the API Guide and the API Viewer would also be a good idea. It is packed with examples, the one you want for this is one of the examples under 'CallWindowProc' and is called 'Register Server (2)'. The simplest thing would be to just re-register all the DLLs on the startup of the App. The only downside is that the older versions will not be unregistered so as you update the DLLs the old reg entry will be left hanging around. There is also the consideration of 'rights' on the client's machines, but whatever one does, they must have rights. Actually you could UnRegister all the DLLs on closedown of the App, that would be the cleanest idea. Definitely the best solution. You'll need to get a client machine that does not know about the App, and repeatedly test this using system rollback. =================== Going back to your earlier points. 1) Alternatives to AX DLLs I am a bit of a bigot when it comes to AX DLLs, and AX in general. I intensely dislike the dependence on the Registry AX EXEs are not so bad, as they register temselves by simply running them - It is supposed to be running them with /register in the Command line - but I've noticed that the seem to register themselves anyway Realistically you don't have many options - but I persomnally write my DLLs in Delph 2) Unless you are using DCOM then it does not really matter where the DLLs are Just as long as your App can locate them. To Windows, the remote drive is just another drive, it could be a local hard disk for all Windows cares 3) I don't really understand why such a fuss is made about 'marshalling' If one uses Early Bound DLLs VB knows a bit more about the procedures inside the DLLs so it can go (nearly) straight to them. If one uses Late Bound DLLs then VB just treats it as an Object so it has to fossic around checking that they exist. It is AX EXEs that are fascinating, they involve cross process communication I'm pretty sure that this is just done via SendMessage. When it comes to DCOM, I am fairly ignorant, but it looks to me as if there is a despatch mechanism, so it is pumping things down the wire instead of using SendMessage. Fortunately you are not using DCOM so we don't need to worry. 4) I would be pretty surprized if you are passing Structures via COM They are of course, the way 'real' DLLs work, and the APIs work - but the idea of COM was/is to pass simple variables or Objects. I think you might be using 'real DLLs with Type Libraries defining the parameters - not a bad idea, Bruce McKinney (author of Hardcore VB) put all the Windows API declarations in a Type Library If that is what you are doing, then it is probably blurring the distinction between 'real' DLLs and AX DLLs - of course a DLL written in most languages other than VB can be both 'real' and AX at the same time The thing is that MS wrote Windows using C, ASM and Structs, but then they got hooked on the COM stuff - they really do want you to write a method for every little property. They want us to use Classes rather than UDTs - there is some logic in it, and at times it is rather nice. I am pretty sure that you are not passing Structs via COM, I've certainly never seen any legitimate way of doing it, but I could be wrong. Delphi certainly does not permit it - and Borland are pretty unrestrictive. 5) Pretty much covered in 4) Except for putting Application DLLs in the System directory I really would not do that, whatever MS says, it just spatters your App all over the place. All your DLLs belong in one place, In my opinion the only things that should go in the Windows and Windows\System32 directories, are things provided by Microsoft. I'm not too well up on VBA inside Excel, so I'm curious to hear how you get on finding out where your App is running from. Chances are VBA will know somehow, if the worst comes to the worst you can write a little 'shell' in VB that launches Excel - I'm not sure that you have not already done that. Anyway, the more I think about it, the more I am convinced that your solution is to Register the DLLs on startup and UnRegister them on close of App. Jiggering the PATH= in the Environment strings might be necessary, but it is pretty easy and I /know/ that it works. However I strongly suggest that you look at that News Group I suggested earlier, the people there will point you to VBA News Groups if they are unsure. It is always wise to get at least three opinions. I look forward to hearing how you get on. |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: mathtalk-ga on 05 Mar 2005 08:42 PST |
Per frde-ga, I did indeed jump to the erroneous conclusion that "running a COM dll across a network" meant using DCOM, which is why I broached the issue of custom marshalling. If you are using a DLL hosted within a process as the COM provider, then its pointers share an address space with your process and there is no interception & marshalling. As frde-ga had the insight to realize, it seems you are basically using the network drive that has the DLL as a mapped drive for each client PC. The tricky part here is that the mapping may be different on different PC's (or even on the same PC from one reboot to the next). regards, mathtalk-ga |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: plucktick-ga on 19 Apr 2005 07:23 PDT |
frde and mathtalk: many thanks for your comments. I thought you would like to know that the issue has now been solved, in the end it turned out to be simply a matter of not just believing the VBA project's Tools References that each COM dll was registered, but double checking that each COM really was registered. I was looking at the VBA project from a client machine, and seeing that a particular COM dll, call it COM1.dll was appearing with a tick next to its checkbox in Tools and References for that VBA project, I had assumed that this meant that COM1.dll was registered (with the correct path) on the client pc. However, it appears that this does NOT imply anything about the state of registration of the dll, it is merely information that is stored in the VBA project's .xls or .xla file. The VBA project may even compile even if the dll is not registered, because VBA has access (through the path to references stored in the .xls or .xla file) to the dll's type library! Once I had realised this, it was easy to check which COM dlls were not registered (e.g. by opening up a brand new excel VBA application and project and seeing which dlls appeared as available references), and I could then reregister them in an automated way on each client pc via a .bat file. So in the end, no marshalling (because all the dlls, being dlls rather than exes, are run in the local process of Excel.exe) nothing more complicated than making sure each dll was registered (but hindered by some counter-intuitive behaviour by Excel VBA : perhaps it should really give some error message when compiling if the dll's aren't registered?). Regards, and thanks once again! pluctick |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: frde-ga on 19 Apr 2005 21:59 PDT |
@PluckTick Glad to hear that you have solved the problem. Also thanks for coming back to 'close' the thread. |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: mathtalk-ga on 20 Apr 2005 05:51 PDT |
Yes, thanks for sharing the hard-won knowledge! --mt |
Subject:
Re: Problem: get error 429 when running a COM dll across a network
From: plucktick-ga on 20 Apr 2005 08:18 PDT |
You're welcome, and thanks once again for your help! |
If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you. |
Search Google Answers for |
Google Home - Answers FAQ - Terms of Service - Privacy Policy |