C# Plugin Implementation Query - c#

I am trying to write a plug-in for an application. The only thing I am provided with is a dll resource file which defines an interface; here's the code:
using System;
using System.Drawing;
namespace App.Plugin.Resources.Interface
{
public interface IAppPlugin
{
string Name { get; set; }
string Description { get; set; }
string Author { get; set; }
string Version { get; set; }
Icon MenuIcon { get; set; }
EventHandler PluginEventHandler { get; set; }
}
}
I then created a class that implemented this interface, made it display a message box, compiled the dll, placed it in the Plugins folder of the application and when the application executed and launched the plugin, it did display the message.
It seems to me that the software offers the means to execute external code (through the plugin system), but doesn't actually give access to any of the application's properties or methods.
Considering the above, my question is: Am I able to interact with the host process in any other way (e.g. get informed when a menu item is selected or even add a menu item myself to the main GUI) with the given resources or does this plugin system just act as an application launcher (by executing the code in the dll I'm providing)?

This seems just an application launcher, not a real plugin, unless there is some strategy implemented by convention: maybe the app looks at the plugin constructor with reflection, and pass some interfaces to the host system, or it looks for some properties marked with some custom attributes to pass some entry points.Another possible vehichle to pass the main application entry points is the PluginEventHandler, try to see in debug what you receive when the plugin is invoked. In addition, try to look with some tools as ILspy to see if there is something more in the plugin instantiation.

Related

Kofax Export Connector registration

I want to create a Kofax Export Connector and register it in the Administration module. I created a Class Library (.NET Framework) with the following code for the setup and release
KfxReleaseSetupScript.cs
namespace Kofax_CoBRA_Export
{
[Guid("b826cc5a-ed80-4fe1-a80f-86a08cca2851")]
public interface IKfxReleaseSetupScript
{
ReleaseSetupData SetupData { get; set; }
KfxReturnValue OpenScript();
KfxReturnValue CloseScript();
KfxReturnValue RunUI();
KfxReturnValue ActionEvent(KfxActionValue action, string dataStringOne, string dataStringTwo);
}
[Guid("39a4f6f6-0de1-40b2-8934-d9a7c2c79468")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Kofax_CoBRA_Export.KfxReleaseSetupScript")]
internal class KfxReleaseSetupScript : IKfxReleaseSetupScript
{
// Interface Implementation
}
}
KfxReleaseScript.cs
namespace Kofax_CoBRA_Export
{
[Guid("091d8f6c-b4c4-42d4-81aa-3b86b31ce46d")]
public interface IKfxReleaseScript
{
ReleaseData DocumentData { get; set; }
KfxReturnValue OpenScript();
KfxReturnValue CloseScript();
KfxReturnValue ReleaseDoc();
}
[Guid("e034c243-ae35-4823-9f2f-10bb6a6fe5c0")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("Kofax_CoBRA_Export.ReleaseScript")]
internal class KfxReleaseScript : IKfxReleaseScript
{
// Interface Implementation
}
}
My .inf registration file contains this code
[Scripts]
Kofax_CoBRA_Export
[Kofax_CoBRA_Export]
SetupModule=.\bin\Debug\Kofax_CoBRA_Export.dll
SetupProgID=Kofax_CoBRA_Export.KfxReleaseSetupScript
SetupVersion=1.0
ReleaseModule=.\bin\Debug\Kofax_CoBRA_Export.dll
ReleaseProgID=Kofax_CoBRA_Export.KfxReleaseScript
ReleaseVersion=1.0
SupportsNonImageFiles=True
RemainLoaded=True
SupportsKofaxPDF=True
SupportsOriginalFileName=True
SupportsMultipleInstances=False
DisplayName=Kofax_CoBRA_Export
When I select the .inf file in the adminstration module I just get an empty box so there is nothing to install.
I took the information from
Kofax Capture Developer's Guide 10.0.0
KCEC-Text Exporter Sample
Kofax Capture API Reference Guide
Kofax Capture Export Type Library
but I really don't get why I get anything to install in the administration module. Any help would be appreciated.
When providing a relative path, Kofax expects the binaries in its own directory (usually C:\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin on a server, as admin.exe runs using this working path). In your case that would translate to C:\Program Files (x86)\Kofax\CaptureSS\ServLib\Bin\bin\Debug\Kofax_CoBRA_Export.dll.
Note that Kofax recommends copying all custom binaries including your inf file to the server directory, however I prefer creating a sub folders for my code, putting all files there. Then, my inf file would look as follows:
[Scripts]
SmartCAP.KEC.EnergieAG.SAP
[SmartCAP.KEC.EnergieAG.SAP]
SetupModule=SmartCAP.KEC.EnergieAG.SAP.dll
SetupProgID=SmartCAP.KEC.EnergieAG.SAP.Setup
SetupVersion=11.0
ReleaseModule=SmartCAP.KEC.EnergieAG.SAP.dll
ReleaseProgID=SmartCAP.KEC.EnergieAG.SAP
ReleaseVersion=11.0
SupportsNonImageFiles=True
SupportsKofaxPDF=True
Note that Kofax still needs to be able to resolve all dependencies you used in your solution - most definitely internal ones such as the Kofax.ReleaseLib.Interop.DLL - so, you could either copy them there, or - that's what I'd prefer, use a custom assembly resolver in your code, pointing to the server directory.

Crystal Reports doesn't allow me to select datasource

I'm working on windows forms application. I want to give crystal reports a .net object as datasource, my "product" class.
it worked for the first report and its working fine.
the problem is when i want to create another report, on "Standard Report Creation Wizard" when i navigate to project data > .net objects > [my class name] and try to include in to my report, this window pops up :|
what this window is asking me for?
I created another project and created a class and report and again it worked fine! so how can i make this work?
Ok, don't go through this avenue. It's much too complicated to set the datasource like this! Instead, go ahead and create the .rpt file, and from the designer in Visual Studio, you can view the database expert. From there, you can add any of your .NET objects.
I've set up a class for you to test as well. I just plugged this into my Reporting project and it works.
public class DummyReportClass
{
public string FieldOne { get; set; }
public string FieldTwo { get; set; }
public string FieldThree { get; set; }
}

Winform app: Compiled App.Config-like file?

I would like to know if there is some kind of built-in compiled "App.Config" file?
The goal is to be able to have one of our library which can have some of its default values overriden when being used in some client application.
Thoses DLL are loaded dynamically, so I cannot just give a parameter in the constructor.
I don't want to use the App.config file because the user can edit those values(otherwise it would have been just fine).
There are several different ways to solve this.
If you like the idea of config-files, but do not want to have it accessible by end users in the compiled application, perhaps you can create your own settings-file in a format that suits your needs, and include it as an embedded resource?
An upside of this would be that you can access it as a regular XML or config file or whatever in Visual Studio, while it will be hidden from the end user. Personally I think I would prefer this to using special code / classes to store config-data.
To include a file as an embedded resource, include it into one of your Visual Studio projects, right click the included file and select Properties. Now under Build Action, select Embedded Resource. When you build your project now, the file will be included internally in the produced .dll-file.
I'm sure you'll be able to find lot's of info about how to access an embedded resource from code. As an example, there are some useful examples in this SO question. Note especially this answer, which also mentions an alternative way to include a resource.
Expanding on my comment... you could just make an interface for a settings class with hardcoded values, and then make different implementations of that interface. To actually change which one to use, all you'd need to do is comment/uncomment the line that instantiates an object into your settings variable before you build the dll:
public class MainDllProject
{
ISettings m_Settings;
public MainDllProject()
{
// Change this before compiling
this.m_Settings = new DebugSettings();
//this.m_Settings = new DeploySettings();
// use settings from the settings class
String setting1 = this.m_Settings.Setting1
Int32 setting2 = this.m_Settings.Setting2
//...
}
}
public interface ISettings
{
String Setting1 { get; }
Int32 Setting2 { get; }
}
public class DebugSettings: ISettings
{
public String Setting1
{ get { return "data_debug";} }
public Int32 Setting2
{ get { return 2;} }
}
public class DeploySettings: ISettings
{
public String Setting1
{ get { return "data_deploy";} }
public Int32 Setting2
{ get { return 1;} }
}
On finding "a built-in way of solving this", as you said, maybe this will be useful for you...
You can actually use the Visual Studio build configuration manager to build with different settings. Using the #If directives, you can automatically make it select which lines of code to use based on the configuration. A simple example based on the default debug configuration, which adds the "DEBUG=True" variable automatically:
public MainDllProject()
{
#If DEBUG Then
this.m_Settings = new DebugSettings();
#ElseIf
this.m_Settings = new DeploySettings();
#End if
}
You can actually make your own custom-named variables to check on just like that DEBUG one: after making a configuration, open the Project properties window, go to the Compile tab, select that specific configuration in the dropdown, and then at the bottom select "Advanced Compile Options". In there is a line "Custom constants" in which you can add such variables. For simple if-statements, you can just make a boolean like "CLIENTDEPLOY=True", and then you can use #If CLIENTDEPLOY Then in your code.

Accessing the configuration file across application domain

We are implementing a plug and play module for our application where user can load and unload the desired class library at runtime. So I have decided to use MEF and shadow copying of class libraries.
The thing here is each class library may have different configuration properties which needs to set by user. My main application has no knowledge about the configurations present in the class library.
Now the problem is when I try to transfer the application configuration file loaded with class library from one application domain to another.
Without MEF, I have just returned Settings.Default from the class library and I have used it in our main application to edit the settings. With MEF and shadow copying, It doesn't seems to be working because
The object type needs to known to both sides.
I cannot implement MarshalByRefObject on the settings file since
the settings file is already extending ApplicationSettingsBase which
is an abstract class and c# doesn't supports multiple inheritance.
Currently I am creating a class which holds all the properties as string and creating a GUI in my main application based on this class content.
public class ExtensionModuleConfiguration : MarshalByRefObject
{
public string Name { get; set; }
public string Value { get; set; }
public List<string> Options { get; set; }
public UIElements ToolUIElement { get; set; }
}
public enum UIElements
{
ComboBox,
TextBox
}
I must say this is not the best solution.
Can someone suggest a better way to set the configurations of a class library in MEF?
There two ways how you can do it. You must inform .NET which app.config should be loaded in the appdomain of your MEF plugin class.
Therefore you can either point particular app.config for your plugin DLL like this:
ConfigurationManager.OpenExeConfiguration("Plugin.dll");
var name = AppSettings.Settings["Name"].Value;
Or you can load the app.config for your main application DLL and put all the appsettings in that file. In this case you should do:
var config = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
var name = config.AppSettings.Settings["Name"].Value;
Both solutions should be called from within of you Plugin implementation for example in constructor. Or by first call to some lazy loaded configuration property.

Having trouble registering assembly for COM

I have created a simple class library project in visual studio 2008 that has one class as shown below. I am trying to get this class to register for COM interop so that I can use in via unmanaged scripts like vbscript or jscript.
In my project build properties I have checked the box that says "Register for COM Interop".
In the Assembly Settings I have checked "Make this assembly COM Visible" and I have confirmed that the [assembly: ComVisible(true)] attribute is present in the assembly.cs file.
Every time I build this project I get an error that reads "projectname.dll does not contain any types that can be registered for COM Interop. Also, I have not been able to successfully create an instance of class 1 using a vbscript. Does anyone know that this is not registering properly?
My vbscript fails to create activex object at this line... Set F = CreateObject("64BitCLTest.Class1").
Finally, how do I get VS to register this in the 64bit area of the registry instead of the 32 bit area so that 64bit processes can use it?
-- The Test Class--
namespace _64BitCLTest
{
[Guid("BBAA06EF-CA4C-4fe2-97CD-9B1D85ADA656")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[ProgId("64BitCLTest.Class1")]
public class Class1
{
Class1()
{
// do nothing
}
public string Method1()
{
return "This is a return string from method 1";
}
public int Property1
{
get {return 777;}
}
}
}
you need to mark the constructor public:
-- The Test Class--
namespace _64BitCLTest
{
[Guid("BBAA06EF-CA4C-4fe2-97CD-9B1D85ADA656")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ComVisible(true)]
[ProgId("64BitCLTest.Class1")]
public class Class1
{
public Class1()
{
// do nothing
}
public string Method1()
{
return "This is a return string from method 1";
}
public int Property1
{
get {return 777;}
}
}
}
There are two parts to this answer. The first, problem as consultutah said was that I did not have the constructor marked as public.
The second answer is that there is a bug (I believe) in VS2008 that causes assemblies to never be registered in the 64-bit section of the registry, even if the setup project is configured for a target platform of x64.
I installed VS2010, rebuilt the exact same project and ran the Install. The assembly registered perfectly and I was able to successfully access it through COM using a 64bit process. I still have not found a solution for this in VS2008.

Categories

Resources