I'd like to implement a small feature (getting default Styles and ControlTemplates for WPF controls) that is missing in SharpDevelop vs. Visual Studio. I'm facing the problem that I do not understand what is considered to be the public API surface for the WpfDesign.Designer addin that I'd like to extend.
Is there an established mechanism for addins to declare in what ways other addins may extend them (addins extending other addins is explicitly allowed in the SharpDevelop architecture)?
The public API surface is all the public types in the WpfDesign.Designer assemblies. You can reference them directly and specify this in your addin's .addin file so the designer addin is loaded before your addin is loaded.
<Manifest>
<Identity name="YourAddInId"/>
<Dependency addin="ICSharpCode.AvalonEdit" requirePreload="true"/>
</Manifest>
Using the public types is the simplest way to extend an existing addin. You reference the designer assemblies, but do not have them copied locally to your addin's output directory.
There are other ways to extend SharpDevelop using extension paths in the addin system. This allows you to have addins that do not depend on each other. The WPFDesigner addin does not define any extension points/paths as far as I am aware so I would just directly reference the designer assemblies and use them.
Also another approach to consider would be to add the changes directly to the SharpDevelop source code and submit a pull request so they can be included in SharpDevelop directly. However an addin might be useful to as a proof of concept.
Related
I'm writing a C# application that accepts plugins. The way I accomplished this is as follows:
In my solution, create a project that contains a single interface that defines the expected methods of a plugin class.
In the main application, add a reference to this project containing one interface.
Add a third project to the solution which represents a plugin. This plugin also has a reference to the interface project.
In my main application, I scan a plugins folder for files matching a given filename (plugin_.dll). If such files are found, I load the assembly and then use reflection to look for any class that implements the interface. For any such class, I add an instance of it to a List<IPlugin>. The app then has access to all the plugins via this list.
This works great and I have successfully written a couple of very simple plugins.
Here's where I'm struggling:
When I want to test the plugin, I have to first build the solution and then manually copy the built plugin into the correct location which the app scans. I know I can probably automate this by adding a post-build command though.
More importantly, is there a good way to actually debug the code in the plugin? (single-step, exception breaks, etc.) Right now I simply run the app and see what happens. I use extensive Console.WriteLines if I need to trace something. It's far less productive though than using VS's debugger.
Less important at this particular point but could be a thing down the road: how would someone else debug the plugin? More specifically: if I start a new VS solution and make a reference to the interface assembly, is there any reasonable way to debug the code in my new plugin?
We have managed to build an outlook addin for 2010,2013 and 2016. We have created an OL2010 vsto project and fiddled with the .csproj file(1*). The problem is that few types were added in 2013/2016 and we can't access them. We only want to access them if the respective OL version is used of course.
As far as i understand the whole thing:
The Interop assemblies are delivered with the addin. So its theoretically possible to inject some IL code or provide additional assemblies with the same namespace that provide those missing types. Since those Interop assemblies are only COM Wrapper and the functionallity relies on unmanaged code which is provided by the installed Outlook version they should get loaded seamlessly when imported correctly.
Is that somehow feasible?
What could go wrong if i try this/deploy the addin to the client?
How could i proceed to determine if i need to use a higher version Interop Type?
How can i load the higher Interop Type?
How can i use it without conflicting existing types?
As i want Intellisense and static typing. I have to predefine those types and decorate them with Guid, CoClass, and TypeLibType. Will that be enough?
(1*)(we changed the DebugInfoExeName and the OfficeVersion in the ProjectName.csproj file and built the respective installer with different virtual machines where the corresponding outlook versions are installed. Maybe there is an easier way? -> let me know!...sadly we can't use addin-express because of some reasons.
I would preferably not use the complete OL 2016 Interop Assemblies since it is throwing exceptions when used from other Threads than the main threads. And we have some synchronization code which has to be run in the background.
Thank you for any answers!
"Creating interops manually: In Visual Studio, just add a COM reference to an application of the Office 2000 suite to the project. This automatically creates the interop you need. But it is the point where your problem begins: a great number of classes and events are inaccessible, because a number of identical bugs in Office type libraries make Studio create the interop that will not work for you. You can disassemble the interop, make unavailable classes and events public, and recompile it (ildasm.exe and ilasm.exe). This is exactly the way Add-in Express version-neutral interops were created."
source: https://social.msdn.microsoft.com/Forums/en-US/a95cd4e3-e619-4846-be2a-ce4c235ff457/is-it-possible-to-use-the-microsoftofficeinteropoutlook-that-comes-from-office-2010-with-all?forum=outlookdev
EDIT
Checkout this project
https://github.com/netoffice/NetOffice-NuGet
It contains version neutral interop assemblies though the structure and namespaces dont match... But still could be useful.
Situation
I run a build system that executes many builds for many project. To avoid one build impacting another we lock down the build user to only its workspace. Builds run as a non privileged users who only have write ability to the workspace.
Challenge
During our new build we need to use a legacy 3rdparty DLL that exposes its interface through COM. The dev team wants to register the build(regsrv32.exe) but our build security regime blocks this activity. If we relax the regime then the 3rdparty DLL will impact other builds and if I have two build which need two different versions I may have the wrong build compile against the wrong version (a very real possibility).
Question
Are there any other options besides registration to handle legacy DLLs which expose their interface via COM?
Thanks for the help
Peter
For my original answer to a similar question see: TFS Build server and COM references - does this work?
A good way to compile .NET code that references COM components without the COM components being registered on the build server is to use the COMFileReference reference item in your project/build files instead of COMReference. A COMFileReference item looks like this:
<ItemGroup>
<COMFileReference Include="MyComLibrary.dll">
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMFileReference>
</ItemGroup>
Since Visual Studio provides no designer support for COMFileReference, you must edit the project/build file by hand.
During a build, MSBuild extracts the type library information from the COM DLL and creates an interop assembly that can be either standalone or embedded in the calling .NET assembly.
Each COMFileReference item can also have a WrapperTool attribute but the default seemed to work for me just fine. The EmbedInteropTypes attribute is not documented as being applicable to COMFileReference, but it seems to work as intended.
See https://learn.microsoft.com/en-ca/visualstudio/msbuild/common-msbuild-project-items#comfilereference for a little more detail. This MSBuild item has been available since .NET 3.5.
It's a shame that no-one seems to know anything about this technique, which to me seems simpler than the alternatives. It's actually not surprising since I could only find just the one above reference to it on-line. I myself discovered this technique by digging into MSBuild's Microsoft.Common.targets file.
There's a walkthrough on registration-free COM here:
http://msdn.microsoft.com/en-us/library/ms973913.aspx
And excruciating detail here:
http://msdn.microsoft.com/en-us/library/aa376414
(the root of that document is actually here: http://msdn.microsoft.com/en-us/library/dd408052 )
Also, for building in general, you should be able to use Tlbimp or tlbexp to create a TLB file that you can use for building, assuming the point of registering is just to be able to compile successfully, and not to run specific tests.
Installation tools such as Installshield can extract the COM interfaces from the DLLs and add them to the registry. It can also use the self-registration process of the DLL (which I believe is what regsvr does), but this is not a Microsoft installer best practice.
in .NET COM is normally done thru Interop in order to register .DLL in .NET they are called Assemblies and that can be done several ways.. by adding references via VS IDE at the project level, or writing code that Loads and unloads the assembly.. by .Config file that haas the reference to the assembly as well as the using of that reference within the project... GAC.
If you have access to the 3rd party .DLL's you can GAC them, and reference them in your project
you can add a using to your .cs file header as well as add the reference to the project by right clicking on reference --> add Reference ...
you can also do the above step as well as set the copy local = true in the properties for that .dll.. I hope that this gives you some ideas.. keep in mind that .NET assemblies are Managed code so there are several ways to Consume those 3rd party .DLL's using other methods within C# like LoadFromAssembly ect..
Thanks for all the help.
We changed from early-binding to late-binding because we never really needed the DLL at compile time. This pushed the registration requirement from the build server to the integration test server (where we execute the installer which handles the registration). We try to keep the build system pristine and have easy-to-reset integration systems.
Thanks again
Peter
I have an image editor user control(c# .net v2.0). Its used in thousands of computers as an activex component. I want the component also be available for windows forms and possible other uses.
For activex usage i add <object> tag in html code and call the component with clsid(a static guid). So if i build and distribute a newer version it works without changing any client code.
I want windows forms to be able use the same distributed libraries. And they should not reference a specific version so i can update the component without changing the programs that use it.
I use regasm to register for com. But i dont know how to reference it from visual studio(like referencing with clsid?)
May be in visual stuido when i choose add reference and select COM tab i shuld see my component in the list.
note: i tried to add the assemly to the global cache using these lines but it did not work out-or i coulnt understand if anything has changed :)
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\tlbexp" ImageEditorComp.dll /out:ImageEditorComp.tlb
regasm /tlb:ImageEditorComp.tlb ImageEditorComp.dll
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\gacutil" /I ImageEditorComp.dll
Any suggestions appreciated,
Regards
This is not possible, you'll invoke the infamous and dreaded DLL Hell problem. A stone cold hard rule in COM is that you have to change the [Guid] attribute values on public interfaces when you make a breaking change in either the publicly visible interfaces or the implementation of them. Changing the guids ensures that you don't overwrite the registry keys of an old version of your component when you use Regasm.exe. Existing programs that use your component and were not recompiled to use the latest version will continue running without problems. The typical outcome of DLL Hell is a nasty hardware exception like AccessViolation, very difficult to troubleshoot.
None of which applies in your specific case here. There is no point in trying to use the component through COM. It is a .NET assembly, just add the reference to it directly. The IDE will in fact stop you from adding a reference to the interop library. But not the .tlb. The GAC keeps you out of DLL Hell, assuming you properly increment [AssemblyVersion].
I figured out a solution.
To explain step by step:
1- Create the component with all needed properties for com.(Sign the assembly, use interfaces for com, make assembly com visible)
On the client machine
2- Register the assembly with regasm(i recommend adding safety flags too).
3- Add the assembly to the global cache using gacutil(or msi installer)
I figured out when you call a specific version of an assembly gac is searched in the first place so if its installed in GAC, referenced codebase path is never used.
When using as activeX you address the component with GUID. Since regasm adds the assembly name and version the GUID is representing, web browser directly uses component from GAC.
When using from a desktop application, reference the assebmly directly and set copylocal property to false. Similarly, in the client machine windows will find the assembly located at GAC itself.
Here is a useful link about the subject.
http://www.simple-talk.com/dotnet/visual-studio/build-and-deploy-a-.net-com-assembly/
Hope it saves other peoples time :)
Here's what I'd like to do:
I want to create a library project that contains my Resource files (ie, UI Labels and whatnot). I'd like to then use the resource library both in my UI and in my Tests. (Ie, basically have a common place for my resources that I reference from multiple projects.)
Unfortunately, because the StronglyTypedResourceBuilder (the .Net class which generates the code for Resources) makes resource files internal by default, I can't reference my strongly typed resources in the library from another project (ie, my UI or tests), without jumping through hoops (ie, something similar to what is described here, or writing a public wrapper class/function).
Unfortunately, both those solutions remove my ability to keep the references strongly-typed.
Has anyone found a straight-forward way to create strongly typed .Net resources that can be referenced from multiple projects?
I'd prefer to avoid having to use a build event in order to accomplish this (ie, to do something like replace all instances of 'internal' with 'public', but that's basically my fall-back plan if I can't find an answer..
Not sure which version of Visual Studio you are using, so I will put steps for either one:
VS 2008 - When you open the resx file in design view, there is an option at the top beside Add Resource and Remove Resource, called Access Modifier, it is a drop down where you can change the generated code from internal to public.
VS 2005 - You don't have the option to generate the code like in VS 2008. It was a feature that was added, because of this headache. There are work around's though. You could use a third party generator like this tool or you could use the InternalsVisibleTo attribute in your AssemblyInfo.cs to add the projects that will have access to the internal classes of your resource library.
Visual Studio 2008 allows you to select whether the generated resource class should be internal or public. There is also the ResXFileCodeGeneratorEx, which should do that for Visual Studio 2005.
From the dataset designer and with the properties window visible, there is a "Modifier" property. For your datasets, it is likely saying internal.
I don't know if there is a setting to default all new datasets to public.