Add non .NET DLL to ColdFusion - winforms

I am currently faced with a dilemma in regards to adding any kind of DLL to a ColdFusion project. I have done a ton of research but nothing seems to be simplistic enough to grasp an understanding. I have a Winform that uses the same DLL in the Reference which makes life easy. When looking to add the same DLLs to a ColdFusion project, it doesn't seem to be working. I have tried using the following:
<cfobject type="com" name="myObj" assembly="C:\DocViewer\AxInterop.SHDocVw.dll">
Here is the error message I am receiving as well:
Attribute validation error for tag CFOBJECT. It has an invalid
attribute combination: assembly,name,type.
This site has been very helpful in the past and I am hoping to learn how this DLL in CF9 works so that I do not have to completely rewrite an entire program when the current one works perfectly.
From comments
I tried adding the DLL using the regsvr32 but here is my error now:
the module was loaded but the entry-point dllregisterserver was not found

Well it looks to me like you're using the cfobject attributes for a .NET object instead of for a COM object. The cfobject tag is one of those tags where the attributes vary by action/type, like cfcontent, cffile and cfdirectory (and a bunch of others that don't immediately spring to mind).
So you need the documentation for accessing COM objects specifically, which for the latest version of Adobe's CFML engine is located here: https://wikidocs.adobe.com/wiki/display/coldfusionen/cfobject%3A+COM+object
There's a typo on the docs page, but it looks like this should work for you (although I'll admit it's been a while since I've invoked a COM object):
<cfobject
type = "com"
class = "path.to.com.Class"
name = "myObj"
action = "create|connect">
It looks like you would use action="connect" if you have it installed as a Windows Service, or create if you want CF to instantiate the DLL, but I would guess having it installed as a service would be easier. I'm just guessing, but I think "path.to.com.Class" would be the name of the service if you're using it that way, or it would be the logical path to the .dll file if the CF server is instantiating it. If neither of those options work, then there might either be a version incompatibility if this is being moved to a newer OS, or the service might be misconfigured.
The error message from registering the DLL sounds like (and I'm guessing because I've never created a windows service DLL) it's looking for a specific class or function in the DLL in order to register it as a service in Windows and it can't find that "entry point" in the DLL (i.e. in the same way that Java will look for a "public static void Main(String args)" as the entry-point to a Java program). That may be necessary for a Service, but it's probably not necessary for a generic DLL that might be accessed and used in some other way, so it's possible this DLL might work, but not be compatible with Service registration.
So going back to your sample code, this might work:
<cfobject type="com" name="myObj" action="create"
class="C:\DocViewer\AxInterop.SHDocVw.dll">

Related

Using log4net on nmodbus from not-main-project in a WPF project

So, i'm taking over a old project that uses nmodbus (and old version at that, 2.0_1.11.0.0, we decided it was best to not update). Nmodbus uses log4net for logging messages. I need to be able to view the logged messages, but it seems like log4net doesnt like WPF, or being in not-main-project.
Adding
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
To the Nmodbus project AssemplyInfo.cs file gives me this error:
Severity Code Description Project File Line Suppression State
Error Unknown build error, 'Cannot resolve dependency to assembly 'log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.' OptimalProdTest
Adding log4net, with NuGet Package Manager, to the main (WPF) project causes Nmodbus to stop working. (maybe has something to do with log4net being an older version in the old nmodbus project, and adding with NuGet will download the newest? Can i somehow add log4net from the other project into the main project without NuGet?)
I found other people with similiar problem who said i should add:
FileInfo configFileInfo = new FileInfo("log4net.config");
log4net.Config.XmlConfigurator.ConfigureAndWatch(configFileInfo);
to "the entry point of your library setup your logger", one guy said, another said "in the constructor of the wrapper class". However, i do not know what files these guys are talking about, nor do i know which project they meant (add to main project or nmodbus?).
( https://social.msdn.microsoft.com/Forums/vstudio/en-US/0c5d7fbb-94a3-4221-ab91-9732c5acee58/cannot-resolve-dependency-to-assembly-because-it-has-not-been-preloaded )
I'm lost and i can't find much help when googling. Anyone has any idea what i should do to be able to view the logs from log4net in nmodbus?

Sharing string resources between Windows desktop and Windows store app

I’m working with an application for both Windows desktop and Windows store, potentially I will add Windows Phone in the future. I’m having most of my logic in a library and create different GUI for the different platforms.
I want to localize my application and want to share string resources between the platforms. But how do I do that?
For Windows desktop the most common approach seems to be using resx files. Here is a short example:
http://compositeextensions.codeplex.com/discussions/52910
For Windows store app resw files are used instead, here is an example of that:
http://msdn.microsoft.com/en-us/library/windows/apps/hh965326.aspx
Both these solutions are platform specific which I don’t like :-(. I really want to have all my string in one file/language and being able to use that in all platforms. Is there any solution for this?
Update 17 Feb 2014: As I understand it resx and resw files are in the same format. What is missing in Windows store app is that no class file is generated for the resw file. If I just could get a file like that my problems would be solved. Then I could put an instance of that class in my view model and access all text via properties.
The class file generated in WPF application almost works. The problem is this line that looks something like this:
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ResxTest.Properties.StringTest", typeof(StringTest).Assembly);
To get this to compile I need to change it to this:
global::System.Resources.ResourceManager temp = new System.Resources.ResourceManager("ResxTest.Properties.StringTest", typeof(StringTest).GetTypeInfo().Assembly);
But the resource ResxTest.Properties.StringTest can’t be loaded in my Windows Store application. For some reason I need to rename my resource to Resource.resw and load it with the name “Resource”. I have tried all kind of names but this is the only one that works. Using name MyApplication.MyResource never works.
I’m not sure if I’m on the right track. I’m almost so desperate that I will make my own solution were I convert an XML-file with all strings I needed to a huge class with properties that I could use to get all string without any resource files. But I think that is ugly and cheating so I hope someone could give me a better idea :-).
Update 24 Feb 2014: I was wrong! Things are working quite nicely with Portable class library. If I use that I could put an instance of auto generated C# class in my view model and access all strings from that object.
But if I use an ordinary library things doesn’t work as properly in Windows Store app (WPF is fine). I have tried to copy all files to a Windows store class library from a working Portable class library. When I try to create an instance of the auto generated file I always get:
An exception of type 'System.Resources.MissingManifestResourceException' occurred in mscorlib.dll but was not handled in user code
Additional information: Unable to load resources for resource file "MetroLib.StringResources" in package…
Quite annoying since I’m using the express editions of Visual Studio where portable class library isn’t available. So probably I will develop my own solution to generate classes from a resource file (which also gives me some other benefits). But I’m still curious what I’m doing wrong.
I finally solved the problem. I simply developed a simple tool (ResToCode) to convert resource files to pure C# classes. Quite similar to what Visual Studios resgen.exe is doing, but with some extra features. It works really well so I’m quite happy about it :-).
The tool is available for anyone at CodeProject:
http://www.codeproject.com/Articles/744528/ResToCode-Localization-tool-for-Windows-Desktop-St
You can put all your resources in a Portable class library and use these libraries on all platform. You might have to check what version of .NET framework you are using. Portable libraries are not available on all the versions of all the platforms.
http://msdn.microsoft.com/en-us/library/vstudio/hh871422(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/vstudio/gg597391(v=vs.110).aspx#members
Have you looked at the Multilingual App Toolkit? It keeps the translations in an industry standard XLIFF format and can generate resources files for Windows and Windows Phone.
I had the same issue with the MissingManifestResourceException for Portable Class Libraries too. Today I created a new Portable Class Library with another name (without the string 'Resources' in it): and it works like a charm. No idea why this hasn't worked before (perhaps the name of the resource).

Obfuscate Silverlight library using Dotfuscator

I'm attempting to use Dotfuscator 4.7.1000 to obfuscate a Silverlight library that is strongly named. When I attempt to do so, I get the following error message:
External type not found
System.Data.Services.Client.LoadCompletedEventArgs,System.Data.Services.Client,
Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
I have tried adding this assembly to the GAC, and have tried adding user defined assembly load paths to the configuration to locations where this assembly is located to no avail.
I then tried adding System.Data.Services.Client to the input assemblies and ran it again. This time it gets further, but ultimately I get:
Warning: Password protected Strong Name files are not supported
sn returned 1.
It appears as though it is attempting to run sn.exe on System.Data.Services.Client.dll with my local key. I've tried excluding this assembly from any obfuscation tasks, but it continues to do so.
Is there something I'm missing when trying to obfuscate this library? Is there some other way to directly point it to the DLL it can't seem to find that I don't know about? Or can I include the DLL in the project without it trying to obfuscate the Silverlight library?
And for the moment, please no suggestions on alternate obfuscators. My company has a license for Dotfuscator and I'd like to get this running using that. Thanks!
Somehow I must have been screwing up my user defined assembly load paths. As soon as I re-added the path to the Silverlight 4.0 client DLLs everything worked without having to reference System.Data.Services.Client.

Loading modules in Prism from xap without reference

I'm using Prism 4 with Unity. I have a main project, and a module. The module is created as Silverlight Applications, so it builds a separate xap file.
I load the modules in the Bootstrapper's ConfigureModuleCatalog, just like the documentation states.
var moduleType = typeof (MyModule);
this.ModuleCatalog.AddModule(
new ModuleInfo
{
ModuleName = moduleType.Name,
ModuleType = moduleType.AssemblyQualifiedName,
InitializationMode = InitializationMode.WhenAvailable,
});
Everything works fine, but I notice that my main xap file also contains the dlls associated with my module. So, I set Copy Local = False on the module reference, and it builds correctly with the module dlls only in their own xap file.
But now my app won't run because I can't get the type information for MyModule. I get a FileNotFoundException.
I found that I can drop the reference entirely if I manually enter the ModuleName and ModuleType, and also set Ref = "MyModule.xap" on the ModuleInfo. This works fine, but here's the problem: I build frequently and use dynamic verion numbers. So the AssemblyQualifiedName changes too easily. Without the reference, there's no way to get it dynamically. If I drop the version number from the AssemblyQualifiedName, it doesn't work.
Surely there's some other way to get the module to load from its own xap file without it ending up also in the main xap?
Nevermind...
After researching further, it seems my mistake is in using wildcard versioning in the assembly version. It is suggested on many sites to use the wildcard in the assembly FILE version only, and use fixed version numbers on the assembly version. Then I can just drop the reference and refer to the module by its strong name with fixed version number.
I was so locked in to prism on this one. I didn't figure it out until I thought about assembly location in general. The post that solved it for me actual was about resolving sharepoint parts. Just goes to show sometimes you have to think outside the box.
Update
Looks like you can't use the wildcard in the file version... grr... I found an add-in that will work though http://autobuildversion.codeplex.com/
Anyone got a better idea?

Attempting to load a DLL on Windows using LoadLibrary when a dependent DLL is missing

I have an application that uses LoadLibrary on Windows to dynamically load plugins. However some of the plugins have other dependent DLLs, such as database client DLLs.
When you attempt to load such a DLL and one of the dependent DLLs doesn't exist you get a nasty Windows dialog:
"The program can't start because xxx.ddl is missing from your computer. Try reinstalling the program to fix this problem."
Is there any easy way to avoid this dialog? I was hoping one could use LoadLibraryEx and pass a flag that says "don't give me that annoying dialog", but it doesn't seem like it.
What I'd like is for the application to handle that error, rather than Windows handling it for me, especially as the text of the message is incorrect (the problem isn't that the program can't start, the program is running quite happily, it just can't load this plugin).
What I'd like to avoid is having to rewrite the plugins that have these external dependencies to make them themselves do a dynamic load of any dependent modules and then query for any entry points.
Anyway, any suggestions would be gratefully received.
Use SetErrorMode(). Use it with SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS before you load the DLL and with 0 right after.
From MSDN:
To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function.
Link here

Resources