Creating a COM module in X# for a Visual Objects application using Visual Studio

(Side-by-Side / DLL registration with manifest)

It is not too difficult to create a X# DLL and use it from VO; you can even enter other languages like C# in the same DLL and call C# methods from X# (or v.v.).

You can refer to docs.xsharp.it/doku.php?id=com_module_sample in which Wolfgang explains the procedure using Xide. I have done it in Visual Studio

To use the DLL, you need to register it, as follows:

Regasm WCFINterfaces.dll /tlb (in an Admin DOS prompt)

This can be avoided which is easier for installing the program to a customer but it is more of a challenge. These are the steps:

X#

The GUID is a unique number and one can be created at https://www.guidgenerator.com/online-guid-generator.aspx. E,g,

587BF093-A8F9-4119-12EB-414AA8FCF344

In the startprogram after BEGIN NAMESPACE add the following 3 lines, with the generated guid from above. Note that there are no empty lines in between. The code then looks as follows:

BEGIN NAMESPACE DotNetLibForVO
[ClassInterface(ClassInterfaceType.AutoDual)];
[Guid("587BF093-A8F9-4119-12EB-414AA8FCF344")];
[ComVisibleAttribute( TRUE )];
CLASS VoDotNetClass
PROTECT lInvalid AS LOGIC 

  CONSTRUCTOR()
  RETURN
METHOD SaveImageFromClipboard(cFile AS STRING) AS LOGIC
//#s Save jpg cFile from clipboard DvK 15-9-2014
//#p cFile: path+file

LOCAL data AS System.Windows.Forms.IDataObject
LOCAL image AS System.Drawing.Image
LOCAL lCreated AS LOGIC

IF (System.Windows.Forms.Clipboard.GetDataObject() != NULL)
	data := System.Windows.Forms.Clipboard.GetDataObject()
	IF (data:GetDataPresent(System.Windows.Forms.DataFormats.Bitmap))
		image := (System.Drawing.Image)data:GetData(System.Windows.Forms.DataFormats.Bitmap, TRUE) 
		image:Save(cFile, System.Drawing.Imaging.ImageFormat.Jpeg)
		lCreated:=TRUE
	ELSE
		lCreated:=FALSE
	ENDIF
ELSE
	lCreated:=FALSE
ENDIF
RETURN lCreated

Enter the 3 lines below on Post build Event Comment Line. Note that you may need to check the exact location of mt.exe and make sure that you do not use the mt.exe in x86 if you are on a 64 bits Windows. This should work too:

"$(FrameworkSDKDir)bin\mt.exe" -

But it's better not to rely on it.

Also note the rem in red, omit it in the first run.

rem "C:\Program Files (x86)\Windows Kits\10\bin\x64\mt.exe" -managedassemblyname:$(TargetFileName)  -nodependency -out:$(ProjectDir)\$(ProjectName).manifest
"C:\Program Files (x86)\Windows Kits\10\bin\x64\mt.exe"  -manifest "$(ProjectDir)\$(ProjectName).manifest" -outputresource:"$(TargetFileName)"
Copy "$(TargetDir)*.dll" "d:\SomeDirWithWriteRights"

At Run the post-build event choose: On successful build

VO

RESOURCE CREATEPROCESS_MANIFEST_RESOURCE_ID RC_RT_MANIFEST c:\VoManifests\ChosenName.manifest

It could look as dollows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="iconnect.exe" version="2.0.0.0" type="win32" processorArchitecture="*" />
<description>This file helps to load the .NET Components without registration in the registry</description>
<description>It should be linked as RC_RT_MANIFEST in the VO EXE</description>
 
<dependency>
 <dependentAssembly>
  <assemblyIdentity name="DotNetLibForVO" version="1.0.1.1" processorArchitecture="msil" />
 </dependentAssembly>
</dependency>
 
<description>Visual Objects Application.</description>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="X86"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
 
</assembly>
METHOD PasteImage () CLASS Something
LOCAL oDotNet AS OBJECT
//….
oDotNet:= OLEAutoObject{"DotNetLibForVO.VoDotNetClass"}
oDotNet:Finit
cTempFilename:=GetTempFilePath()+"lImage.JPG"
lOk:=oDotNet:SaveImageFromClipboard(cTempFilename)

Also note that you may come across Finit errors. This usually means that the manifest is not correctly 'recognized”. You may need to try more than once to touch the manifest mef, rebuild the project, or maybe even reindex. IF the program doesn't start, this may also something which can be solved after multiple retries. If it persists, also try to create an .exe and if that works the program may work from the VO IDE as well. Otherwise:

In Start menu select Event viewer and go to Windows logs, Application. This may show:

Activation context generation failed for “d:\XSharpVOTest\XSharpVOTest.DBG”.Error in manifest or policy file “d:\XSharpVOTest\DotNetLibForVO.DLL” on line 1. Component identity found in manifest does not match the identity of the component requested. Reference is IC2ExtLibForVO,processorArchitecture=“x86”,version=“1.0.65534.65534”. Definition is DotNetLibForVO,processorArchitecture=“msil”,version=“1.0.65534.65534”. Please use sxstrace.exe for detailed diagnosis.

Note that the architecture In yellow is what Windows found in the manifest and in blue what was found in the DLL (from the project settings in e.g. VS). The manifest line in 8), see in blue, must match the one in the DLL, otherwise this error occurs.

SXTrace

The program should be at location: C:\Windows\System32\sxstrace.exe Administrative privileges are required to use sxstrace.exe

Note: Make sure you run the command on a directory with write permissions. As an alternative, point the –logfile parameter to a directory with write permissions

sxstrace.exe Parse -logfile:tracetest.log -outfile:tracetest.txt

Sample:

C:\Windows\System32\sxstrace.exe Trace -logfile:c:\temp\tracetest.log C:\Windows\System32\sxstrace.exe Parse -logfile:c:\temp\tracetest.log -outfile:c:\temp\tracetest.txt

Sample: courtesy by Dick van Kooten