I've been rather confused by some SGEN stuff. I've enable the generation of serialization assemblies for one of my projects. Originally I got the follow error which I believe I've solved by doing some caspol stuff on a remote assembly.
Unable to load one or more of the request types. Retrieve the
LoaderExceptions propery for more information
Now however, I don't get an assembly generated. Adding some debugging/verbose output provides the message "SS.dll does not contain any types that can be serialized using XmlSerializer". I've read that this is because of a proxy switch applied by VS. The odd thing is it doesn't seem to be a problem with any other project.
So if I disable the proxy switch (example here) it seems to work. The linked build events however seem to do all projects. I don't know enough about MSBuild to tweak to just a single project, does anyone know what I need to change?
Additionally, if this change is made, is there a way I can automatically include this in a installer (VDProj)? I can't statically link to the SS.XmlSerializers.dll because the each dev uses a custom path.
Discovered the following post which talks about adding the <SGenUseProxyTypes>Off</SGenUseProxyTypes> to the csproj file which seems to work :)
Related
Assume you have a .DLL file, and you want to know some basic information regarding it,
for example:
Is it a Managed (.NET) or Non-Managed (e.g. COM, etc) DLL
If it's Managed, what minimal version of .NET it requires
(and if it's non-managed, then any other minimal version that it requires? for example minimal version of Windows, or of something else)
Any other kind of such metadata
Please note that I am less interested in seeing the Function Headers (or Classes) that are inside.
Visual Studio's Object Browser can show the Functions/Classes very well,
yet I did not find a way to make Object Browser show the metadata that I mentioned above..
So maybe another utility can do it?
I created a multi-module project with a single sonar-project.properties. Most of the project is in c but one module is c++. I left the sonar.language property blank and ran sonar-runner with analysis.
The project and modules were created in the database and everything looked OK but when I did a preview on the same code I had a large number of new issues on the c++ project.
On closer inspection I found that the module in sonarqube was all wrong - it consisted of only the header files (.h) and most of the issues were the use of C style comments. It seems that the module was identified as a C module so all the .cpp files were ignored. However, in the preview the language was identified correctly and issues were found in the .cpp files that were clearly not know to sonarqube.
I cannot find any place in the UI to change the language of a module nor can I figure out a way to force it after the fact in my sonar-project.profiles.
First, sonar.language is apparently deprecated, and second, using module.sonar.language=cpp caused an error:
Caused by: sonar.profile was set to 'DEFAULT_C' but didn't match any profile for any language. Please check your configuration.
DEFAULT_C is something that we use for projects generally but not the one I'm working on. I have different profiles set up for different languages via the UI, but if I cannot get the analysis to see the correct language it doesn't help me much.
Any one have any idea how I can force the language of a module after the fact?
Hmm. I considered just deleting this but if I had found an answer on stackoverflow it would have eased my pain a little.
Brute force works.
Just set the language and the profile you want for the moudle and ignore complaints about such things being deprecated. Chosing a language won't force the right profile even if you have set up an explicit profile for the language in the UI - so just state it in the sonar-project.properties file.
In my case:
module.sonar.language=cpp
module.sonar.profile=MY_CPP_PROFILE
Throw sonar-runner at that and it will beat the backend into shape.
With the risk to fall into too specific question...
Given a C++ MFC (mixed, not shaked) project compiled with /CLR, I have 200 classes already defined.
When I add a new empty class to this project, an error raises when I compile and execute in debug mode.
An unhandled exception of type 'System.IO.FileLoadException' occurred
in Unknown Module.
Additional information: Could not load file or assembly 'ProjectA,
Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its
dependencies. Could not find or load a type. (Exception from HRESULT:
0x80131522)
ProjectA is the name of the MFC project itself. There is no reference to any ProjectA assembly on project configuration, and there is no reference to another custom assembly.
This project only have references to some .NET Framework assemblies, in order to allow that some of custom defined classes in the project can use CLR classes.
Then, the question is...
Do you know whether there is any limitation of class number on a MFC C++ project?
EDIT:
As I say in comments, in release mode the compilation succeed without errors.
Also, I clean, build, clean, close Visual Studio, reboot computer... and the problem still appears.
If I keep in 200 classes, there is no error. When I go to 201, the error appears.
Currently I'm trying to reproduce in a new default MFC project, adding classes till arrive to 200, to confirm that there is a real limitation.
EDIT 2: ERROR FIXED
Great. #MSX and #frymode show me how avoid the error with his comments.
In the Visual Studio development environment (source / source):
Open the project's Property Pages dialog box.
Click the C/C++ folder.
Click the Code Generation property page.
Modify the Enable String Pooling (/GF) property.
Thank you guys!
The /GF hack is a known workaround for this problem. It is however not a correct one, you are putting a band-aid on a heavily bleeding wound. Pretty important that you heal the problem instead of putting a patch on it, this heavily affects the way your program runs at runtime as well.
The problem maker is the <Module> class, an internal class that the C++/CLI compiler generates. You can see it with ildasm.exe or a good decompiler. This class is required as a home for declarations in your program that are not class members, valid in native C++ but not supported by the CLR. Which demands that every variable or function declaration is a member of a class. The C++/CLI compiler solves it by moving such a declaration into the <Module> class.
There is however a limit on the number of members in a class, they are represented in the metadata of the .NET assembly with a metadata token. An index into other tables. The upper byte identifies the table number, the lower bytes are the index in the table.
You exceeded that limit. This is bad.
A problem with the /clr compile option is that it works too well. It is capable of compiling any C++03 compliant native C++ code to MSIL. Such code will be just-in-time compiled to machine code by the jitter, just like normal managed code. It is however not verifiable code and it doesn't act like managed code at all, you can blow up your program with pointer fumbles just as easily. And above all, it is not code that's optimized with the native C++ back-end. Only the jitter optimizer has a shot at improving that code, it cannot do nearly the quality job that the native C++ optimizer can do, given that it runs with a hard upper limit on how much time it can spend on doing that job.
Have a look-see with a decompiler to see what ended up in that <Module> class. That's going to be overwheliming at first, you know you've got a big one right now. You fix this problem by spending more time segregating the code into the managed parts and the native parts. Where the native code should be compiled without /clr in effect. It is a per-source file setting, you can even switch back-and-forth in a single source code file with #pragma managed. The simplest way to segregate is by keeping your native code in its own library or DLL.
This link shows that there's no limit to the number of types you can have in a namespace (not a project). Considering, that a namespace can be split across different assemblies, you could, at least in theory, have an unlimited number of types. However, this post affirms that the maximum number of classes in a .DLL
is 16777215. Probably, you'll run out of memory before you reach that number of classes :)
Just for information: there seems to be a limit to the number of fields per class, though.
P.S.:
Here's the solution to your problem taken from this link
Open the project's Property Pages dialog box.
Click the C/C++ folder.
Click the Code Generation property page.
Modify the Enable String Pooling property.
I want to add my own project type based on IronStudio. So,
I downloaded the source for and compiled the latest version of IronPython, then
I created a new Visual Studio Package.
I added the Templates\Projects\MyProject folders, and added a file to it, and set its property "Include in VSIX" to true.
Then modified the main Package class to be derived from IronStudio's PythonProjectPackage instead, and set the ProvideProjectFactory property:
[ProvideProjectFactory(
typeof(PythonProjectFactory),
"Django Project",
"Django Project Files (*.myproj);*.myproj",
"myproj", "myproj",
#"Templates\Projects\MyProject",
LanguageVsTemplate="MyProject")]
public sealed class MyPackage : PythonProjectPackage
And ran it. But MyProject isn't showing up in the project templates. Why not?
The generated .pkgdef file looks like this:
[$RootKey$\InstalledProducts\VSPackage3Package]
#="#110"
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"PID"="1.0"
"ProductDetails"="#112"
"LogoID"="#400"
[$RootKey$\Packages\{5cd7435c-7461-459f-80bc-c0c79e9d462f}]
#="Microsoft.VSPackage3.VSPackage3Package, VSPackage3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a4f1577d825253f8"
"InprocServer32"="$WinDir$\SYSTEM32\MSCOREE.DLL"
"Class"="Microsoft.VSPackage3.VSPackage3Package"
"CodeBase"="$PackageFolder$\VSPackage3.dll"
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}]
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\Extensions]
"py"=dword:00000020
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\LogicalViews]
"{7651a701-06e5-11d1-8ebd-00a0c90f26ea}"=""
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\LogicalViews]
"{7651a702-06e5-11d1-8ebd-00a0c90f26ea}"=""
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\LogicalViews]
"{7651a703-06e5-11d1-8ebd-00a0c90f26ea}"=""
[$RootKey$\CLSID\{888888fd-3c4a-40da-aefb-5ac10f5e8b30}]
#="Microsoft.IronPythonTools.Project.PythonGeneralPropertyPage"
"InprocServer32"="$WinDir$\SYSTEM32\MSCOREE.DLL"
"Class"="Microsoft.IronPythonTools.Project.PythonGeneralPropertyPage"
"CodeBase"="$PackageFolder$\VSPackage3.dll"
"ThreadingModel"="Both"
[$RootKey$\Projects\{888888a0-9f3d-457c-b088-3a5042f75d52}]
#="PythonProjectFactory"
"DisplayName"="My Project"
"DisplayProjectFileExtensions"="My Project Files (*.myproj);*.myproj"
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"DefaultProjectExtension"="myproj"
"PossibleProjectExtensions"="myproj"
"ProjectTemplatesDir"="$PackageFolder$\Templates\Projects\MyProject"
"Language(VsTemplate)"="MyProject"
[$RootKey$\NewProjectTemplates\TemplateDirs\{5cd7435c-7461-459f-80bc-c0c79e9d462f}\/1]
#="My Project"
"SortPriority"=dword:00000064
"TemplatesDir"="$PackageFolder$\Templates\Projects\MyProject"
[$RootKey$\Projects\{888888a0-9f3d-457c-b088-3a5042f75d52}]
#="PythonProjectFactory"
"DisplayName"="IronPython"
"DisplayProjectFileExtensions"="IronPython Project Files (*.pyproj);*.pyproj"
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"DefaultProjectExtension"="pyproj"
"PossibleProjectExtensions"="pyproj"
"ProjectTemplatesDir"="$PackageFolder$\.\NullPath"
"Language(VsTemplate)"="IronPython"
[$RootKey$\NewProjectTemplates\TemplateDirs\{5cd7435c-7461-459f-80bc-c0c79e9d462f}\/1]
#="IronPython"
"SortPriority"=dword:00000064
"TemplatesDir"="$PackageFolder$\.\NullPath"
[$RootKey$\Services\{b98e41c4-581e-3532-beee-06829b683d39}]
#="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"Name"="IPythonStarter"
I just want to get the bare bones up and running so I can start overriding some functionality (like the Add New Item dialog).
Update:
Reading my initial analysis once again increases my impression that some of the required components are missing (e.g. a dedicated ProjectFactory) and/or wired up incorrectly - from the MSDN documentation of the ProvideProjectFactoryAttribute Class:
ProvideProjectFactoryAttribute declares that a package provides a project factory.
And further:
If a VSPackage declares that it provides a project factory, it should create the factory and offer it to Visual Studio in the Initialize method of the Package-derived class.
You package is declaring to provide PythonProjectFactory, but (likely) doesn't offer it to VS, rather it is offered by the IronPython package. In turn you are providing arguments within the ProvideProjectFactory attribute list which PythonProjectFactory won't know about when asked for by VS.
Consequently you should at least provide a dedicated ProjectFactory yourself as per the walkthrough, wire up the classes accordingly and see how this turns out regarding the issues outlined below.
Initial analysis:
There appear to be several issues here at first sight - have you followed any tutorial on how to do this? In case, please note that some of those easily discoverable via search engines are outdated still. Either way I'd try working through and/or comparing your result with Walkthrough: Part 1 - Creating a Basic Project System from the MSDN documentation for VS 2010; please note that even this one is claimed to be outdated a bit according to the Community Content section on the bottom of the page.
Here is what I'd look into myself given the code you present, comparing with the walkthrough on the fly for more insights:
You realized already that the duplicate fragment starting with the GUID above PythonProjectFactory doesn't make sense - this is essentially trying to register two packages at once, which, even if allowed at all syntactically (which I doubt), can't possibly work like so due to both being registered with the same GUID [cross checking with the sample file in section Examining the Template Registration confirms this suspicion, as expected there is only one such fragment].
Please note that the GUID in question is the one identifying PythonProjectFactory (as per the respective source code), see below for more on this.
[Guid(PythonConstants.ProjectFactoryGuid)]
public class PythonProjectFactory : ProjectFactory {
Given .pkgdef is a generated file the next question is where this duplication/violation stems from. When two generated artifacts end up with the same GUID the respective definition in the sources is most likely messed up somehow, usually due to copy&paste duplication. Consequently you should verify whether {5cd7435c-7461-459f-80bc-c0c79e9d462f} is defined and referenced as intended, though here might be one or two other causes as well for this, see below.
A Package class needs to be identified by a GUID and the VS wizard generates some already in Guids.cs and references it accordingly on the class definition, however, the following is missing in your fragment [cross checking with the sample fragment in section To register the project template confirms this omission as well]:
[Guid(GuidList.guidMyPackagePkgString)]
public sealed class MyPackage : Package
Likewise it appears incorrect to derive MyPackage from PythonProjectPackage but reference PythonProjectFactory still rather than providing MyFactory as well (including a dedicated GUID), because the latter tells Visual Studio the location of your project template folder [see section Creating a Skeletal Project Factory]:
While it might well be possible to simply reuse all functionality from the base class PythonProjectFactory, inheriting is likely required simply because the factory must have a dedicated GUID too (as outlined in the walkthrough) in order to properly wire up the attribute specified data.
Likely unrelated, but still suspicious is that your two code blocks don't relate, as the Package class definition specifies Django Project Files (*.myproj);*.myproj, yet the result shows My Project Files (*.myproj);*.myproj.
Have you by chance mixed this from different builds or is this really a result of a clean one?
Good luck!
This stackoverflow posting might be helpful: VS2010: VSIX installation doesn't deploy item templates inside it
If this is not what you're looking for, try to see if you're missing something around the creation of custom project templates, I believe that's where the "missing link" is:
For VS 2008:
http://blogs.msdn.com/b/webdevelopertips/archive/2008/12/02/tip-32-did-you-know-how-to-easily-create-your-own-project-templates.aspx
For VS 2010:
http://blog.reybango.com/2010/09/21/how-to-create-html5-website-and-page-templates-for-visual-studio-2010/
and on MSDN:
http://msdn.microsoft.com/en-us/library/s365byhx.aspx
and here is how to create a project
template manually:
http://msdn.microsoft.com/en-us/library/ms185291.aspx
and here is how to create a new item template in VS 2010: http://msdn.microsoft.com/en-us/library/ms247113.aspx
Hope this helps
$PackageFolder$.\NullPath may have something to do with it.
This I think is related to my use of the nlog C++ API (and my question on the nlog forum is here); the purpose of my asking this question here is to get a wider audience to my problem and perhaps to also get some more general ideas behind the VB6 IDE's failure to build in my particular scenario.
Briefly, the problem that I am having is that I am having trouble building VB6 components which reference unmanaged C++ components which have calls to nlog's C\C++ API (which is defined in NLogC.DLL). The build problems are not occurring during compile time, they are occurring when the binary is being built which suggests to me that it's some kind of linker type problem? Don't know enough about how VB6 binaries are produced to tell. The VB6 binary is produced, but it is corrupted and crashes shortly after it is invoked.
Has anyone had any similar experiences with VB6 (doesn't have to be related to nlog or C++)?
edit: Thanks for all the responses to this rather obscure problem. Still no headway unfortunately; my findings since I posted this:
'Tweaking' the compile options doesn't appear to help in this problem.
Adding a reference to the nlog-enabled C++ component from a 'blank' VB6 project doesn't crash it or cause weird build problems. So it isn't a 'native' VB6 issue, possibly an issue with the interaction between nlog and the various components and 3rd party libraries used by other referenced components?
As for C++ calling conventions: the nlog-enabled C++ component is - as far as I can see - compliant to these conventions and indeed works fine when referenced by VB6 as long as it is not making any nlog API calls. Not sure if the nlogc.DLL itself is VB6 compliant but I would have thought that that is immaterial since the API calls are being made from the C++ component; VB6 shouldn't know or care about what the C++ component is referencing (that's as far as my understanding on this goes...)
edit2: I should also note that the error message obtained during build is: "Errors during load. Please refer to "xxx" for details". When I bring up the log file, all that there is in there is: "Cannot load control xxx". Interestingly, all references to that particular control disappears from that particular project resulting in compile errors if I were to try to build again.
Got around the problem by using NLog's COM interface (NLog.ComInterop.DLL) from my unmanaged C++ code. Not as easy to do as the C\C++ API but at least it doesn't crash my VB6 components.
I would try tweaking some of the Compile options found in the Project, Properties menu, Compile panel to see if they yield any additional hints as to what is going wrong.
For example if you compile the executable to p-code rather than native code does it still crash on startup.
What error message do you get when you run your compiled binary?
I doubt the compiler/linker is the problem: project references in a VB6 project are not linked into the final executable. A project reference in VB6 is actually a reference to a COM type library (which may or may not be embedded in a .dll or other binary file type). Project references primarily serve two purposes:
The IDE extracts type information from the referenced type libraries which it then displays in the Object Browser (and in the Intellisense drop-down)
At compile-time, the compiler extracts the type information stored in the referenced libraries, including the CLSID of each class that you instantiate, and embeds this data into the executable. This allows your executable to create instances of classes contained in the libraries that you referenced.
Note that the compiled binary doesn't link to any code in the referenced libraries, and it doesn't even contain the filenames of the referenced libraries. The final executable only contains the CLSID's and other type information that it needs to instantiate COM objects at run-time.
It is much more likely that the issue is with NLog, or with how you are calling it from your code, rather than something gone awry in the VB6 compile process.
If you think it might be a linker problem, this should crash it the same way:
create a new standard project (of any kind)
add a new module and copy the "declare"-statements into it
compile
If it doesn't crash it is something else.
It would help an exact description of the error or a screenshot of what going on.
One thing to check is wherever NLogC.DLL or the C++ DLL you built have the correct calling convention defined. Basically you can't have the DLL function names mangled or use anything but the STDCALL calling convention. If the C++ DLL has not been created with those two things in mind then it will fail to work with VB6.
MSDN Article on Calling convention.
"Cannot load control xxx" errors can be caused by .oca files which were created from a different version of an .ocx than currently used. If that is the case, deleting the .oca files helps.