Details needed on creating a custom conflict resolver using a COM based approach
-
Tuesday, December 04, 2012 5:01 PM
The directions that I am trying to follow are here and they're duplicated below:
http://www.replicationanswers.com/CustomResolver.asp
Directions:
- Open a Visual Studio .NET 2003 Command Prompt
- tlbimp "c:\Program Files\Microsoft SQL Server\80\COM\replrec.dll" /OUT:SQLResolver_import.dll
- ildasm "SQLResolver_import.dll" /OUT=SQLResolver.il
- Change line "[out] object& marshal( struct) pvBuffer" for the methods GetSourceColumnValue, GetDestinationColumnValue, and SetColumn to "[out] int32 pvBuffer"
- ilasm SQLResolver.il /OUT=SQLResolver.dll /dll
- Create a new .NET Windows Control Library project
- Remove the wizard generated control
- Use "Add New Item..." to add a new COM class
- Add reference to SQLResolver.dll created in step #5
Step 1a. cd C:\Program*Files*x86*\Microsoft*Visual*Studio*11.0\VC\
Step 1b. execute vcvarsall.bat
Step 2a. cd c:\Users\Current_User\Desktop\
Step 2b. Output messages executing tlbimp "C:\PROGRA~1\MICROS~3\100\com\replrec.dll" /out:SQLResolver_import.dll
Microsoft (R) .NET Framework Type Library to Assembly Converter 4.0.30319.17929
Copyright (C) Microsoft Corporation. All rights reserved.TlbImp : warning TI3002 : Importing a type library into a platform agnostic assembly. This can cause errors if the type library is not truly platform agnostic.
TlbImp : warning TI3015 : At least one of the arguments for 'SQLResolver_import.
IReplRowChange.GetSourceColumnValue2' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.TlbImp : warning TI3015 : At least one of the arguments for 'SQLResolver_import.
IReplRowChange.GetDestinationColumnValue2' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.TlbImp : warning TI3015 : At least one of the arguments for 'SQLResolver_import.
IReplRowChange.SetColumn2' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.TlbImp : warning TI3015 : At least one of the arguments for 'SQLResolver_import.
CLRBusinessLogicModuleClass.GetSourceColumnValue2' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.TlbImp : warning TI3015 : At least one of the arguments for 'SQLResolver_import.
CLRBusinessLogicModuleClass.GetDestinationColumnValue2' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.TlbImp : warning TI3015 : At least one of the arguments for 'SQLResolver_import.
CLRBusinessLogicModuleClass.SetColumn2' cannot be marshaled by the runtime marshaler. Such arguments will therefore be passed as a pointer and may require unsafe code to manipulate.TlbImp : Type library imported to c:\Users\Current_User\Desktop\SQLResolver_import.dll
Step 3.
- Change line "[out] object& marshal( struct) pvBuffer" for the methods GetSourceColumnValue, GetDestinationColumnValue, and SetColumn to "[out] int32 pvBuffer"
There are no methods GetSourceColumnValue, GetDestinationColumnValue, and SetColumn. For example, the file SQLResolver.il has the below. Question: Should I change all of the below methods that refer to "[out] object& marshal( struct) pvBuffer"?
Some of the file's contents are:
.method public hidebysig newslot abstract virtual instance void RemoteGetSourceColumnValue(uint32 ColumnId, [out] object& marshal( struct) pvBuffer, [in] uint32 cbBufferMax, [out] uint32& pcbBufferActual) runtime managed internalcall { } // end of method IReplRowChange::RemoteGetSourceColumnValue .method public hidebysig newslot abstract virtual instance void GetSourceColumnValue2(uint32 ColumnId, [out] native int ppBuffer, [in] uint32 cbBufferMax, [out] uint32& pcbBufferActual) runtime managed internalcall { } // end of method IReplRowChange::GetSourceColumnValue2 .method public hidebysig newslot abstract virtual instance void RemoteGetSourceColumnValueWithStatus(uint32 ColumnId, [out] object& marshal( struct) pvBuffer, [in] uint32 cbBufferMax, [out] uint32& pcbBufferActual, [out] uint32& pDBStatus) runtime managed internalcall { } // end of method IReplRowChange::RemoteGetSourceColumnValueWithStatus .method public hidebysig newslot virtual instance void RemoteGetSourceColumnValue(uint32 ColumnId, [out] object& marshal( struct) pvBuffer, [in] uint32 cbBufferMax, [out] uint32& pcbBufferActual) runtime managed internalcall { .override SQLResolver_import.IReplRowChange::RemoteGetSourceColumnValue } // end of method CLRBusinessLogicModuleClass::RemoteGetSourceColumnValue .method public hidebysig newslot virtual instance void GetSourceColumnValue2(uint32 ColumnId, [out] native int ppBuffer, [in] uint32 cbBufferMax, [out] uint32& pcbBufferActual) runtime managed internalcall { .override SQLResolver_import.IReplRowChange::GetSourceColumnValue2 } // end of method CLRBusinessLogicModuleClass::GetSourceColumnValue2 .method public hidebysig newslot virtual instance void RemoteGetSourceColumnValueWithStatus(uint32 ColumnId, [out] object& marshal( struct) pvBuffer, [in] uint32 cbBufferMax, [out] uint32& pcbBufferActual, [out] uint32& pDBStatus) runtime managed internalcall { .override SQLResolver_import.IReplRowChange::RemoteGetSourceColumnValueWithStatus } // end of method CLRBusinessLogicModuleClass::RemoteGetSourceColumnValueWithStatus
Below is the only SetColumn method in the file. It doesn't have the "out" parameter! What should I do with this?
.method public hidebysig newslot abstract virtual instance void RemoteSetColumn(uint32 ColumnId, [in] object& marshal( struct) pvBuffer, uint32 cbBuffer) runtime managed internalcall { } // end of method IReplRowChange::RemoteSetColumn- Edited by Software Engineering Stuff Tuesday, December 04, 2012 5:05 PM
All Replies
-
Tuesday, December 04, 2012 5:07 PMModerator
Yes, change all method parameters [out] object& marshal( struct) pvBuffer to [out] int32 pvBuffer.- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:16 PM
- Unmarked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:20 PM
- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:36 PM
-
Tuesday, December 04, 2012 5:09 PMModerator
Also, as we can see, there have been some changes to the API since this document was written: Creating Merge Replication Custom Conflict Resolvers Using Visual Basic.- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:16 PM
- Unmarked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:20 PM
- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:36 PM
-
Tuesday, December 04, 2012 5:12 PM
What about [in] object& marshal( struct) pvBuffer.
Thanks,
-
Tuesday, December 04, 2012 5:15 PMModerator
- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:16 PM
- Unmarked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:20 PM
- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:36 PM
-
Tuesday, December 04, 2012 5:26 PM
What about the numerous other references to the marshal class such as below. Do I leave them all alone!
.method public hidebysig newslot abstract virtual
instance void RemoteReconcile([in] class SQLResolver_import.IReplRowChange marshal( interface ) pRowChange,
uint32 dwFlags,
[in] class SQLResolver_import.IReplRowChange marshal( interface ) pvReserved) runtime managed internalcall
{
} // end of method ICustomResolver::RemoteReconcile.method public hidebysig newslot abstract virtual
instance void GetResolverProcedureName([out] class [mscorlib]System.Text.StringBuilder marshal( lpwstr) pResolverProcedureName,
uint32 cbResolverProcedureName) runtime managed internalcall
{
} // end of method IReplRowChange::GetResolverProcedureName.method public hidebysig newslot abstract virtual
instance void GetColumnName(uint32 ColumnId,
[out] class [mscorlib]System.Text.StringBuilder marshal( lpwstr) pColumnName,
uint32 cbColumnName) runtime managed internalcall
{
} // end of method IReplRowChange::GetColumnName
.method public hidebysig newslot abstract virtual
instance void LogConflict([in] int32 bLogSourceConflict,
[in] valuetype SQLResolver_import.REPOLE_CONFLICT_TYPE ConflictType,
[in] int32 bOnlyLogIfUpdater,
[in][opt] string marshal( bstr) pszConflictMessage,
[in][opt] int32 bLogConflictOnUpload) runtime managed internalcall
{
.param [2]
.custom instance void [mscorlib]System.Runtime.InteropServices.ComAliasNameAttribute::.ctor(string) = ( 01 00 27 53 51 4C 52 65 73 6F 6C 76 65 72 5F 69 // ..'SQLResolver_i
6D 70 6F 72 74 2E 52 45 50 4F 4C 45 5F 43 4F 4E // mport.REPOLE_CON
46 4C 49 43 54 5F 54 59 50 45 00 00 ) // FLICT_TYPE..
.param [4] = "0"
.param [5] = int32(0x00000000)
} // end of method IReplRowChange::LogConflict- Edited by Software Engineering Stuff Tuesday, December 04, 2012 5:27 PM
-
Tuesday, December 04, 2012 5:35 PMModerator
Leave them alone. At this point I believe we only need to be concerned about changing the buffer parameters of the methods that are defined to be the address of an object, which we have already done.
- Marked As Answer by Software Engineering Stuff Tuesday, December 04, 2012 5:36 PM

