|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Strange problemHi there,
When I run the following on my app's primary thread: System.Type.GetType("System.Windows.Forms.Form") It works as expected. If I then launch a thread via the "BackgroundWorker" class immediately after the above call, and invoke the above again as soon as the thread starts, it now returns null instead. Can anyone explain this. Thanks. Larry Smith wrote:
> Hi there, Change the call to System.Type.GetType("System.Windows.Forms.Form", true);> > When I run the following on my app's primary thread: > > System.Type.GetType("System.Windows.Forms.Form") > > It works as expected. If I then launch a thread via the "BackgroundWorker" > class immediately after the above call, and invoke the above again as soon > as the thread starts, it now returns null instead. Can anyone explain > this. Thanks. This change will cause it to throw an exception if it can't determine the type. The details in the exception might give you an indication as to what is going wrong. -- Tom Porterfield
Show quote
"Tom Porterfield" <tppor***@mvps.org> wrote in message Thanks very much. It's returning "System.TypeLoadException". Docs state that news:u0VilOZFHHA.924@TK2MSFTNGP02.phx.gbl... > Larry Smith wrote: >> Hi there, >> >> When I run the following on my app's primary thread: >> >> System.Type.GetType("System.Windows.Forms.Form") >> >> It works as expected. If I then launch a thread via the >> "BackgroundWorker" >> class immediately after the above call, and invoke the above again as >> soon >> as the thread starts, it now returns null instead. Can anyone explain >> this. Thanks. > > Change the call to System.Type.GetType("System.Windows.Forms.Form", true); > > This change will cause it to throw an exception if it can't determine the > type. The details in the exception might give you an indication as to > what is going wrong. the "... common language runtime cannot find the assembly or the type within the assembly, or cannot load the type". I see no obvious reason for this although I do have a form going on the primary thread (why should this matter though). Can you or anyone else comment? Thanks. Hello Larry,
Have u tried to specify fully qualified name of your assembly? BTW, have u loaded it before calling GetType? >>> When I run the following on my app's primary thread: LS> Thanks very much. It's returning "System.TypeLoadException". Docs>>> System.Type.GetType("System.Windows.Forms.Form") >>> >>> It works as expected. If I then launch a thread via the >>> "BackgroundWorker" >>> class immediately after the above call, and invoke the above again >>> as >>> soon >>> as the thread starts, it now returns null instead. Can anyone LS> state that the "... common language runtime cannot find the assembly LS> or the type within the assembly, or cannot load the type". I see no --- WBR, Michael Nemtsev [C# MVP] :: blog: http://spaces.live.com/laflour "At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche > Hello Larry, All I have to work with is the full namespace and class name. Again, passing > > Have u tried to specify fully qualified name of your assembly? this to "GetType()" works on the main thread (returning the assembly-qualified name) but not on a worker thread. > BTW, have u loaded it before calling GetType? I'm not sure what I really need to do. I have a form going on the main thread so the assembly is obviously loaded, i.e., I can get the fully-qualifed assembly name by passing "System.Windows.Forms.Form" to "GetType()". Doing this on a worker thread then fails. Ok, based on what Jon said I'm guessing that this works because the forms assembly is somehow bound to the main thread but not to the worker thread. Is this right? In any case, given only "System.Windows.Forms.Form" to work with or any other native .NET type for that matter, how can you get the fully-qualifed assembly name even if the assembly isn't loaded. You don't know which assembly contains it and you only have this string to work with. Thanks for your help. Hello Larry,
LS> I'm not sure what I really need to do. I have a form going on the LS> main thread so the assembly is obviously loaded, i.e., I can get the LS> fully-qualifed assembly name by passing "System.Windows.Forms.Form" LS> to "GetType()". Doing this on a worker thread then fails. Ok, based LS> on what Jon said I'm guessing that this works because the forms LS> assembly is somehow bound to the main thread but not to the worker LS> thread. Is this right? Yep, it seems to be the reason of the problem LS> In any case, given only LS> "System.Windows.Forms.Form" to work with or any other native .NET LS> type for that matter, how can you get the fully-qualifed assembly LS> name even if the assembly isn't loaded. You don't know which LS> assembly contains it and you only have this string to work with. Try to load assembly it in your background thread before GetType call You can end up with that you can't load assembly, then u need to use Reflector/ILDASM to get the fully-qualifed name for loading System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 --- WBR, Michael Nemtsev [C# MVP] :: blog: http://spaces.live.com/laflour "At times one remains faithful to a cause only because its opponents do not cease to be insipid." (c) Friedrich Nietzsche Larry Smith <no_spam@_nospam.com> wrote:
> When I run the following on my app's primary thread: I would expect the above call to return null in either thread, > > System.Type.GetType("System.Windows.Forms.Form") > > It works as expected. If I then launch a thread via the "BackgroundWorker" > class immediately after the above call, and invoke the above again as soon > as the thread starts, it now returns null instead. Can anyone explain this. personally - Type.GetType(string) only looks in the currently executing assembly and mscorlib unless the assembly details are specified. In the real code, are you doing this with a string variable instead of the hard-coded type name? If you only ever want to find the above type, just use typeof(System.Windows.Forms.Form). -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too > I would expect the above call to return null in either thread, It does work on the main thread but fails on the worker thread as noted.> personally - Type.GetType(string) only looks in the currently executing > assembly and mscorlib unless the assembly details are specified. > In the real code, are you doing this with a string variable instead of No. I'm actually reading the type on-the-fly from a file. I only have the > the hard-coded type name? If you only ever want to find the above type, > just use typeof(System.Windows.Forms.Form). fully-qualfied path name to work with as a string ("FullNamespace.ClassName"). I need to generate the assembly-qualified name from this however. It will always be a native .NET type. Can you steer me in the right direction. Thanks very much. Larry Smith <no_spam@_nospam.com> wrote:
> > I would expect the above call to return null in either thread, That sounds very odd, and I can't reproduce it. Can you post a short > > personally - Type.GetType(string) only looks in the currently executing > > assembly and mscorlib unless the assembly details are specified. > > It does work on the main thread but fails on the worker thread as noted. but complete program which demonstrates it working in the main thread? > > In the real code, are you doing this with a string variable instead of Well, either the file needs to specify the assembly as well, or if you > > the hard-coded type name? If you only ever want to find the above type, > > just use typeof(System.Windows.Forms.Form). > > No. I'm actually reading the type on-the-fly from a file. I only have the > fully-qualfied path name to work with as a string > ("FullNamespace.ClassName"). I need to generate the assembly-qualified name > from this however. It will always be a native .NET type. Can you steer me in > the right direction. Thanks very much. have a list of assemblies to check for all types, you could just keep Assembly references, and call Assembly.GetType on each of them until you find a match. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Show quote
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message Actually, the "file" I'm reading is source code. I'm reading ".cs" files in news:MPG.1fdb4134489a7b6f98d69e@msnews.microsoft.com... > Larry Smith <no_spam@_nospam.com> wrote: >> > I would expect the above call to return null in either thread, >> > personally - Type.GetType(string) only looks in the currently executing >> > assembly and mscorlib unless the assembly details are specified. >> >> It does work on the main thread but fails on the worker thread as noted. > > That sounds very odd, and I can't reproduce it. Can you post a short > but complete program which demonstrates it working in the main thread? > >> > In the real code, are you doing this with a string variable instead of >> > the hard-coded type name? If you only ever want to find the above type, >> > just use typeof(System.Windows.Forms.Form). >> >> No. I'm actually reading the type on-the-fly from a file. I only have the >> fully-qualfied path name to work with as a string >> ("FullNamespace.ClassName"). I need to generate the assembly-qualified >> name >> from this however. It will always be a native .NET type. Can you steer me >> in >> the right direction. Thanks very much. > > Well, either the file needs to specify the assembly as well, or if you > have a list of assemblies to check for all types, you could just keep > Assembly references, and call Assembly.GetType on each of them until > you find a match. a loaded solution (using an AddIn), extracting the name of a class in the file (including its namespace), and it's this class whose assembly-qualified name I want to find (its base class actually). The IDE itself is able to do this without issue (long story) so presumably I should be able to do it as well (assuming it's not relying on proprietary functions). I'll see if I can condense this to a simple working example and post it as soon as I can (perhaps a day or two). Thanks for your help ... Larry Smith <no_spam@_nospam.com> wrote:
> > Well, either the file needs to specify the assembly as well, or if you The IDE has a list of referenced assemblies, so can easily ask each of > > have a list of assemblies to check for all types, you could just keep > > Assembly references, and call Assembly.GetType on each of them until > > you find a match. > > Actually, the "file" I'm reading is source code. I'm reading ".cs" files in > a loaded solution (using an AddIn), extracting the name of a class in the > file (including its namespace), and it's this class whose assembly-qualified > name I want to find (its base class actually). The IDE itself is able to do > this without issue (long story) so presumably I should be able to do it as > well (assuming it's not relying on proprietary functions). I'll see if I can > condense this to a simple working example and post it as soon as I can > (perhaps a day or two). Thanks for your help ... those assemblies whether or not it contains a type of the given name. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too > The IDE has a list of referenced assemblies, so can easily ask each of Ok, I created a separate test app out-of-the-box and you're right, a call to > those assemblies whether or not it contains a type of the given name. "GetType("System.Windows.Forms.Form") does return null on the main thread as well. In my own app however, it does work on the main thread as discussed. I'm not entirely sure why without a wider investigation but obviously the assembly is loaded in my own app (and already bound to the main thread) but not in the test app (though both apps are running a form at the time of call). In any case, none of this really matters since I'll be dealing with arbitrary types anyway (not just forms) and have to proceed as if the assembly is not loaded. That being the case, do you know what the general steps are for doing this. Since I'm just reading ".cs" files in a project, looking for the "Type" of classes defined in these files (their base classes that is), I'm assuming that for each base class I'm interested in, I can just iterate all referenced assemblies in the project looking for the class' type (e.g., "System.Windows.Forms.Form" for instance). By "referenced assemblies", I mean those assemblies listed under the "References" folder seen under all projects in Solution Explorer (since all base classes in all ".cs" files must be referenced there presumably - is this correct?). If this is in fact correct (I believe so), do you know which functions I now need to be looking at to accomplish this. I already know how to get the list of assemblies seen under the "References" folder of each project but which functions do I then call in order to look up a string in the form "<NameSpace>.<ClassName>" (in order to return its assembly-qualified name). Larry Smith <no_spam@_nospam.com> wrote:
<snip> > I'm assuming that for each base class I'm interested in, I can Well, rather than using the assembly-qualified name, you could load the > just iterate all referenced assemblies in the project looking for the class' > type (e.g., "System.Windows.Forms.Form" for instance). By "referenced > assemblies", I mean those assemblies listed under the "References" folder > seen under all projects in Solution Explorer (since all base classes in all > ".cs" files must be referenced there presumably - is this correct?). If this > is in fact correct (I believe so), do you know which functions I now need to > be looking at to accomplish this. I already know how to get the list of > assemblies seen under the "References" folder of each project but which > functions do I then call in order to look up a string in the form > "<NameSpace>.<ClassName>" (in order to return its assembly-qualified name). assemblies (once) and then call Assembly.GetType on each of the assemblies. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too > Well, rather than using the assembly-qualified name, you could load the That definitely looks promising (probably what I'm after). Thanks again for > assemblies (once) and then call Assembly.GetType on each of the > assemblies. your help. Hello Larry!
>> The IDE has a list of referenced assemblies, so can easily ask each What do you meen by "the IDE" in this context? The IDE doen't matter here.>> of those assemblies whether or not it contains a type of the given >> name. > ... but obviously the assembly is loaded in my own app (and An Assembly is never bound to a Thread, only to an AppDomain.> already bound to the main thread) Are you absolutly sure that it isn't something in you code that causes the error? If you are not able to reproduce this, it will be hard (likely impossible) for anybody (including MS Support Team) to find out what may be wrong. > and have to proceed as if the assembly is not You can easly get any Type-Instance of a Type in a (as far) not loaded > loaded. Assembly by specifing the Assembly-Qualified Name. If the Assembly has not been loaded, it will be loaded by this operation, and the class (and depend classes) will be initialized. Of cause the Assembly must be reachable in any way (eigther through GAC installation or through being within the search-path). It doesn't matter if the assembly is reference or not. It must be just there. > That being the case, do you know what the general steps are You source .cs files??? This sounds like a compilation time "feature".> for doing this. Since I'm just reading ".cs" files in a project, > looking for the "Type" of classes defined in these files (their base Forget about this IDE things. At runtime there is no IDE.> classes that is), I'm assuming that for each base class I'm > interested in, I can just iterate all referenced assemblies in the > project looking for the class' type (e.g., > "System.Windows.Forms.Form" for instance). By "referenced > assemblies", I mean those assemblies listed under the "References" > folder seen under all projects in Solution Explorer An example: You can set a reference to anything you like within your IDE. The referenced Assemblies will only be included as references within the Assemblies Manifest if they are _actually used_ by your code. You can get a List of referenced Assemblies by calling the Assemblies "GetReferencedAssemblies()" method. But it will only return "AssemblyName" objects. If you need the "Assembly" Instance you have to go through AppDomain.GetAssemblies() or through Assembly.Load(). > (since all base Yes.> classes in all ".cs" files must be referenced there presumably - is > this correct?). > I already know how to get the list of assemblies seen under the From the CLR's point of view the Namespace is just on part of the Assembly's > "References" folder of each project but which functions do I then > call in order to look up a string in the form > "<NameSpace>.<ClassName>" (in order to return its assembly-qualified > name). name (there is no "Namespace" property of the Assembly). What would be possible (but I won't recomment this) is to get all Types of an Assembly by it's .GetTypes() method and to lookup the Namespace.ClassName Type within that list. Do not use this that way. Just use Assembly Qualified Names and all will work "automaticly". Do do not have to care about when an Assembly will be loaded or something like that. Type t = Type.GetType("System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); If you do not what to specify this "long and complex" Assembly Qualified Name (it is realy not very user-friendly ;-)), setup a kind of default (fallback) logic. If you are dealing with Types from strings there will be a configuration file (or other form of persistent storage) which holds this strings. You can implement a simple "Namespace->Assembly Parameters" mapping: e.g. <anyTag> <assemblyMappings> <assemblyMapping namespace="System.Windows.Forms" version="2.0" culture="neutral" publicKeyToken="b77a5...." /> <assemblyMapping namespace="...." ... /> </assemblyMappings> </anyTag> * If a full assembly qualified name is entered, you don't have to do anything * If the name is only "Namespace.Class", you have to lookup within the "assemblyMappings" to get the other parameters * If no corresponding "assemblyMapping" is found, throw an Exception (configuration error). Now you have the Assembly Qualified Name, which can be passed to Type.GetType(...). By using the Architecture, you can avoid all unnessersary Reflection stuff, looping through Assemblies, References and Types. GP Thanks for your detailed feedback (appreciated).
> What do you meen by "the IDE" in this context? The IDE doen't matter here. It does in this case. I'm working on an AddIn which runs in the IDE :)> An Assembly is never bound to a Thread, only to an AppDomain. I was really speaking figuratively. That is, the call to "GetType()" returns the correct value when invoked from my app's main thread but not a worker thread. Since a form is running on the main thread at the time I invoke "GetType()", and I'm passing "System.Windows.Forms.Form" to this (and the function succeeds), it seems likely that some type of affinity must exist between the loaded (forms) assembly and the main thread. Otherwise, why does the same call fail on a worker thread. > Are you absolutly sure that it isn't something in you code that causes the The behaviour is consistent (reproducible) in my own app. If I call > error? If you are not able to reproduce this, it will be hard (likely > impossible) for anybody (including MS Support Team) to find out what may > be wrong. "GetType()" on my app's primary thread and it succeeds, and then I immediately lauch my thread on the very next line and call "GetType()" again (as soon as the thread starts), why should it now fail? I don't see what I could be doing that would cause this. > You can easly get any Type-Instance of a Type in a (as far) not loaded I don't have the Assembly-Qualified name which is the issue. That's what I'm > Assembly by specifing the Assembly-Qualified Name trying to find given only a namespace and class name. > You source .cs files??? This sounds like a compilation time "feature". Exactly.> Forget about this IDE things. At runtime there is no IDE. I'm writing an AddIn which runs in the IDE.> This AddIn is targetting a project in someone else's solution (reading the > An example: > You can set a reference to anything you like within your IDE. The > referenced Assemblies will only be included as references within the > Assemblies Manifest if they are _actually used_ by your code. > > You can get a List of referenced Assemblies by calling the Assemblies > "GetReferencedAssemblies()" method. But it will only return "AssemblyName" > objects. If you need the "Assembly" Instance you have to go through > AppDomain.GetAssemblies() or through Assembly.Load(). source files of each project in the solution). I have to target the referenced assemblies in each project that the AddIn is processing. The .NET extensibility API allows you to read the "References" folder for any project in Solution Explorer. From this I can get the referenced assemblies, load them one-by-one and invoke "Assembly.GetType()" as Jon suggested in his last post. I think that may solve the problem. > From the CLR's point of view the Namespace is just on part of the I was going to try that but I think "Assembly.GetType()" will do what I need > Assembly's name (there is no "Namespace" property of the Assembly). What > would be possible (but I won't recomment this) is to get all Types of an > Assembly by it's .GetTypes() method and to lookup the Namespace.ClassName > Type within that list. instead (again, as suggested by Jon). Otherwise, what other choice do I have but to manually search all types returned by "GetTypes()". > Do not use this that way. Just use Assembly Qualified Names and all will While I appreciate your recommendation (detailed in the remainder of your > work "automaticly". Do do not have to care about when an Assembly will be > loaded or something like that. post), it won't work if I understand you correctly. You likely didn't appreciate that nature of my app however (since I really haven't spelled out much detail). The app will be running in the IDE as a VS AddIn. It has to read ".cs" files in the currently loaded solution, identify classes in these files (whose types I don't know ahead of time), and then retrieve the assembly-qualified name of these classes (given only the namespace and class name read from the ".cs" file). I think the method for doing this is now sinking in. As I read each class in a given ".cs" file (its base class actually), I can then iterate the project's references and load each assembly one-by-one, invoking "Assembly.GetType()" until it returns non-null. Would you agree this is the corret approach (it now appears so). Thanks again for your help (any further comments welcome). Hi Larry!
>> What do you meen by "the IDE" in this context? The IDE doen't matter This makes most of my posting obsolete ;-) Sorry for that!>> here. > > It does in this case. I'm working on an AddIn which runs in the IDE :) Ist the problem reproducable by an mini-AddIn? GP "Günter Prossliner" <g.prossliner/gmx/at> wrote in message I haven't tried it that way, only in a standalone (test) app where it fails news:%2366tvt8FHHA.1188@TK2MSFTNGP06.phx.gbl... > Hi Larry! > >>> What do you meen by "the IDE" in this context? The IDE doen't matter >>> here. >> >> It does in this case. I'm working on an AddIn which runs in the IDE :) > > This makes most of my posting obsolete ;-) Sorry for that! > > Ist the problem reproducable by an mini-AddIn? on the primary thread as mentioned in an earlier post. Why it works in my AddIn is anymone's guess at this point. It probably doesn't matter as much anymore however since it really needs to be done the way I mentioned in my last post (AFAIK at this point). I almost certainly will investigate this further at some later point however. I need to ensure it's not symptomatic of some other other problem that could come back to bite me. Anyway, thanks again for your help (very much appreciated).
Show quote
"Larry Smith" <no_spam@_nospam.com> wrote in message I think you have the right way of doing it now, I would just additionally news:%23a0FG38FHHA.1252@TK2MSFTNGP02.phx.gbl... > > "Günter Prossliner" <g.prossliner/gmx/at> wrote in message > news:%2366tvt8FHHA.1188@TK2MSFTNGP06.phx.gbl... >> Hi Larry! >> >>>> What do you meen by "the IDE" in this context? The IDE doen't matter >>>> here. >>> >>> It does in this case. I'm working on an AddIn which runs in the IDE :) >> >> This makes most of my posting obsolete ;-) Sorry for that! >> >> Ist the problem reproducable by an mini-AddIn? > > I haven't tried it that way, only in a standalone (test) app where it > fails on the primary thread as mentioned in an earlier post. Why it works > in my AddIn is anymone's guess at this point. It probably doesn't matter > as much anymore however since it really needs to be done the way I > mentioned in my last post (AFAIK at this point). I almost certainly will > investigate this further at some later point however. I need to ensure > it's not symptomatic of some other other problem that could come back to > bite me. Anyway, thanks again for your help (very much appreciated). suggest that you cache the result of the lookup (whether success or failure) to avoid searching for the same name over and over. Also, are you handling "using" directives? Remember there are two kinds of using directive, one which adds a namespace to the search scope, and one which introduces an alias for a single type. >> Ist the problem reproducable by an mini-AddIn? Does you test app have a reference to the System.Windows.Forms.dll?> > I haven't tried it that way, only in a standalone (test) app where it fails > on the primary thread as mentioned in an earlier post. Why it works in my > AddIn is anymone's guess at this point. It probably doesn't matter as much > anymore however since it really needs to be done the way I mentioned in my > last post (AFAIK at this point). I almost certainly will investigate this > further at some later point however. I need to ensure it's not symptomatic > of some other other problem that could come back to bite me. Anyway, thanks > again for your help (very much appreciated). |
|||||||||||||||||||||||