SAP - How to use windows control as ActiveX in SAP B1 Addon

Source: How to use Password ActiveX from SAP Portal

 

1. Create new VS project as "Windows Form Control Library" (Run VS as administrator)

2. Go to project Property ==> Compile ==> scroll down near botton, check at "Register Com for Interop"

3. Add source code:

Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports Microsoft.Win32
Imports System.Runtime.Remoting.Channels
Imports System.Collections
Imports System.Runtime.Remoting.Channels.Tcp
Imports System.Reflection
' /// <summary>
'/// Steps to create ActiveX control with DotNet
'/// 1.Register to COM Interop: Project property => Build => Register to COM Interop
'/// 2.Class Declaration: Set ProgId for the ActivexControl and class interface as ClassInterfaceType.AutoDual
'/// 3.Construction: Set up the remoting communication channel for data exchange
'/// between ActiveX COM Interop Service and B1
'/// 4.ComRegisterFunction: Register/UnRegister COM
'/// 5.Property: Mark the property of ActiveX used in B1 as ComVisible
'/// </summary>

'''Step 2: ProgId and Classinterface type for Active Control
'''

<ProgId("SAP.ActiveX.UnitStatus")> _
<ClassInterface(ClassInterfaceType.AutoDual)> _
Partial Public Class AAA
Inherits UserControl

Public Sub New()
Try
'InitializeComponent()
'use Remoting for data exchange between AtiveX control COM Service and B1
Dim provider As New BinaryServerFormatterSinkProvider()
provider.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full

' Creating the IDictionary to set the port on the channel instance.
Dim props As IDictionary = New Hashtable()
props("port") = 0
props("name") = DateTime.UtcNow.ToString()

' Pass the properties for the port setting and the server provider in the server chain argument.
'(Client remains null here.)
Dim tcpChannel As New TcpChannel(props, Nothing, provider)

ChannelServices.RegisterChannel(tcpChannel, False)
Catch e As Exception
MessageBox.Show(e.Message)
End Try
End Sub

''' <summary>
''' Step 4: Auto register the activex to COM in registery
''' </summary>
''' <param name="key">the parent registry key</param>
<ComRegisterFunction> _
Public Shared Sub RegisterClass(key As String)
' Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it
Dim sb As New StringBuilder(key)
sb.Replace("HKEY_CLASSES_ROOT\", "")

' Open the CLSID\{guid} key for write access
Dim k As RegistryKey = Registry.ClassesRoot.OpenSubKey(sb.ToString(), True)

' And create the 'Control' key - this allows it to show up in
' the ActiveX control container
Dim ctrl As RegistryKey = k.CreateSubKey("Control")
ctrl.Close()

' Next create the CodeBase entry - needed if not string named and GACced.
Dim inprocServer32 As RegistryKey = k.OpenSubKey("InprocServer32", True)
inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase)
inprocServer32.Close()

' Finally close the main key
k.Close()
End Sub

''' <summary>
''' Auto unregister the activex to COM in registery
''' </summary>
''' <param name="key">the parent registry key</param>
<ComUnregisterFunction> _
Public Shared Sub UnregisterClass(key As String)
Dim sb As New StringBuilder(key)
sb.Replace("HKEY_CLASSES_ROOT\", "")

' Open HKCR\CLSID\{guid} for write access
Dim k As RegistryKey = Registry.ClassesRoot.OpenSubKey(sb.ToString(), True)

' Delete the 'Control' key, but don't throw an exception if it does not exist
k.DeleteSubKey("Control", False)

' Next open up InprocServer32
Dim inprocServer32 As RegistryKey = k.OpenSubKey("InprocServer32", True)

' And delete the CodeBase key, again not throwing if missing
k.DeleteSubKey("CodeBase", False)

' Finally close the main key
k.Close()
End Sub

''' <summary>
''' Step 5: B1 will retieve the password from the active control
''' thus make a COM Visible property for remoting accessing in B1
''' </summary>
<ComVisible(True)> _
Public Property bb() As aaa
Get
Return Me.aa
End Get
Set(value As aaa)
Return
End Set
End Property

 

End Class

4. Build solution, if the error "..COM interop not register...":

- Run "Developer Command Prompt" as administrator

- Change the folder to .net and run command:

C:\Windows\Microsoft.NET\Framework\v4.0.30319>regasm.exe /tlb "C:\Program Files (x86)\xxx\xxx.dll"

5. From SAP B1 Addon Project, Add reference to that dll

6. Declare as item and use.

Dim active As B1ActiveX.Control = oAtiveX.Object
Dim control as control= active .ControlA