Регистрация Бесплатные COM, скриптовые модели, MT.exe и *.RGS скрипты
У меня есть свободный для регистрации C++ COM компонент, чей манифест я генерирую с помощью mt.exe, используя VS2010. Все работает, за исключением того, что я не могу указать, какую модель потоков используют мои классы. Я создал небольшой проект repro, сгенерированный файл манифеста (RGS.dll.embed.manifest
) как следует:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<file name="RGS.dll" hashalg="SHA1">
<comClass clsid="{4EB506E0-0D9C-4281-9B61-F027376E21C3}" tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}"></comClass>
<typelib tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib>
</file>
<comInterfaceExternalProxyStub name="IRgsObject1" iid="{4620CAB8-3E56-42EC-818E-8A55DF9267B7}" tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub>
</assembly>
У меня проблема с узлом comClass
<comClass clsid="{4EB506E0-0D9C-4281-9B61-F027376E21C3}"
tlbid="{6B48D06F-A84C-4B72-A70F-F1B091789E67}"></comClass>
должен иметь атрибут threadingModel, как в примере "Sxs и бесплатная регистрация COM-активации" на следующей странице: http://blogs.msdn.com/b/junfeng/archive/2006/04/20/579748.aspx
Я знаю, что модель потоков не указана в *.tlb
, но из комментария Сен Харада на документах MSDN для mt.exe
, вы должны быть в состоянии указать один в файле сценария регистрации (*.rgs
) http://msdn.microsoft.com/en-us/library/windows/desktop/aa375649(v=vs.85).aspx
Итак, у меня есть *.rgs
файл, созданный мастером ATL
HKCR
{
NoRemove CLSID
{
ForceRemove {4EB506E0-0D9C-4281-9B61-F027376E21C3} = s 'RgsObject1 Class'
{
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{6B48D06F-A84C-4B72-A70F-F1B091789E67}'
Version = s '1.0'
}
}
}
Так что я даю *.rgs
подать в mt.exe
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /out:"Debug\RGS.dll.embed.manifest" /tlb:"Debug\RGS.tlb" /rgs:"RgsObject1.rgs" /dll:"RGS.dll" /manifest Debug\RGS.dll.intermediate.manifest
И посмотрите из журнала сборки, что он успешно проанализировал *.rgs
файл
Valid GUID!!! {4EB506E0-0D9C-4281-9B61-F027376E21C3}
Adding entry ClsidTable[{4EB506E0-0D9C-4281-9B61-F027376E21C3}] = RgsObject1 Class
CManGenLib.ParseFileContents::Appending class {00000000-0000-0000-0000-000000000000}
Processed .RGS file successfully
Found type library in file , guid {6B48D06F-A84C-4B72-A70F-F1B091789E67} (contains 2 types)
CManGenLib.ProcessTlb::Appending class {6B48D06F-A84C-4B72-A70F-F1B091789E67}
Found interface {4620CAB8-3E56-42EC-818E-8A55DF9267B7} 'IRgsObject1'
Processed .TLB file successfully
Looking for pstub {4620CAB8-3E56-42EC-818E-8A55DF9267B7} (IRgsObject1)
(в частности, строка "Действительный GUID!!!" пропала без rgs:
параметр для mt.exe
)
ЕЩЕ мой RGS.dll.embed.manifest
не имеет атрибута threadingModel.
Этот человек - единственный, кого я могу найти в сети, говоря о проблеме, http://social.msdn.microsoft.com/Forums/en-US/vcmfcatl/thread/dbab28cd-023f-45b1-be62-7dc71e8d3d9f, и он никогда нашел решение и отредактировал манифест после того, как он был сгенерирован. Кто-нибудь знает, как инструмент mt.exe использует файл RGS для создания манифеста, и что мне нужно сделать, чтобы получить ThreadingModel на другом конце?
1 ответ
Интересно... похоже, что для того, чтобы mt.exe был счастлив, нужны некоторые рудименты ProgId. В частности, следующее *.rgs
HKCR
{
AtlObjectProgId.1 = s 'AtlObject Class'
{
CLSID = s '{2371607D-284A-4D7C-A6DD-20C15373F43F}'
}
NoRemove CLSID
{
ForceRemove {2371607D-284A-4D7C-A6DD-20C15373F43F} = s 'AtlObject Class'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Free'
}
}
}
}
производит следующее *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="ATLProject2.dll" hashalg="SHA1"><comClass clsid="{2371607D-284A-4D7C-A6DD-20C15373F43F}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" threadingModel="Free"></comClass><typelib tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><comInterfaceExternalProxyStub name="IAtlObject" iid="{81A8B3DA-2AFE-4C25-B0ED-CDD777FB01A4}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>
тогда как следующее *.rgs
HKCR
{
NoRemove CLSID
{
ForceRemove {2371607D-284A-4D7C-A6DD-20C15373F43F} = s 'AtlObject Class'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Free'
}
}
}
}
производит следующее *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="ATLProject2.dll" hashalg="SHA1"><comClass clsid="{2371607D-284A-4D7C-A6DD-20C15373F43F}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}"></comClass><typelib tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><comInterfaceExternalProxyStub name="IAtlObject" iid="{81A8B3DA-2AFE-4C25-B0ED-CDD777FB01A4}" tlbid="{92B1424C-0D03-4909-99DC-2A70EFD210D5}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>
Редактировать: кажется, что это работает, но это работает только для первого класса в *.rgs
файл. Например, следующее *.rgs
HKCR
{
AtlObj1ProgId.1 = s 'AtlObj1 Class'
{
CLSID = s '{D15A646A-4F2F-42C2-BA8B-780AABCFB133}'
}
AtlObj1ProgId = s 'AtlObj1 Class'
{
CurVer = s 'AtlObj1ProgId.1'
}
NoRemove CLSID
{
ForceRemove {D15A646A-4F2F-42C2-BA8B-780AABCFB133} = s 'AtlObj1 Class'
{
ProgID = s 'AtlObj1ProgId.1'
VersionIndependentProgID = s 'AtlObj1ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
AltObj2ProgId.1 = s 'AtlObj2 Class'
{
CLSID = s '{C208B430-8E12-4C65-AA5A-899F6AB13C4B}'
}
AltObj2ProgId = s 'AtlObj2 Class'
{
CurVer = s 'AltObj2ProgId.1'
}
NoRemove CLSID
{
ForceRemove {C208B430-8E12-4C65-AA5A-899F6AB13C4B} = s 'AtlObj2 Class'
{
ProgID = s 'AltObj2ProgId.1'
VersionIndependentProgID = s 'AltObj2ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
}
Производит следующее *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="RgsClass2.dll" hashalg="SHA1"><comClass clsid="{D15A646A-4F2F-42C2-BA8B-780AABCFB133}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" threadingModel="Neutral" progid="AltObj2ProgId"><progid>AtlObj1ProgId.1</progid><progid>AltObj2ProgId.1</progid></comClass><comClass clsid="{C208B430-8E12-4C65-AA5A-899F6AB13C4B}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}"></comClass><typelib tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo><comInterfaceExternalProxyStub name="IAtlObj1" iid="{FF2A4D47-DADA-451E-8125-610643B00FBC}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub><comInterfaceExternalProxyStub name="IAtlObj2" iid="{F9226919-2AB7-4DBE-9F79-092839480351}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>
Обратите внимание, что только первый CoClass имеет ThreadingModel (или ProgId в этом отношении).
Изменить: успех! Следующие *.rgs
HKCR
{
AtlObj1ProgId.1 = s 'AtlObj1 Class'
{
CLSID = s '{D15A646A-4F2F-42C2-BA8B-780AABCFB133}'
}
NoRemove CLSID
{
ForceRemove {D15A646A-4F2F-42C2-BA8B-780AABCFB133} = s 'AtlObj1 Class'
{
ProgID = s 'AtlObj1ProgId.1'
VersionIndependentProgID = s 'AtlObj1ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
}
HKCR
{
AltObj2ProgId.1 = s 'AtlObj2 Class'
{
CLSID = s '{C208B430-8E12-4C65-AA5A-899F6AB13C4B}'
}
NoRemove CLSID
{
ForceRemove {C208B430-8E12-4C65-AA5A-899F6AB13C4B} = s 'AtlObj2 Class'
{
ProgID = s 'AltObj2ProgId.1'
VersionIndependentProgID = s 'AltObj2ProgId'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Neutral'
}
TypeLib = s '{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}'
Version = s '1.0'
}
}
}
производит следующее *.embed.manifest
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="RgsClass2.dll" hashalg="SHA1"><comClass clsid="{D15A646A-4F2F-42C2-BA8B-780AABCFB133}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" threadingModel="Neutral" progid="AtlObj1ProgId"><progid>AtlObj1ProgId.1</progid></comClass><comClass clsid="{C208B430-8E12-4C65-AA5A-899F6AB13C4B}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" threadingModel="Neutral" progid="AltObj2ProgId"><progid>AltObj2ProgId.1</progid></comClass><typelib tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" version="1.0" helpdir="" flags="HASDISKIMAGE"></typelib></file><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges><requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security></trustInfo><comInterfaceExternalProxyStub name="IAtlObj1" iid="{FF2A4D47-DADA-451E-8125-610643B00FBC}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub><comInterfaceExternalProxyStub name="IAtlObj2" iid="{F9226919-2AB7-4DBE-9F79-092839480351}" tlbid="{85D8EC5E-3C24-4151-83D9-34CCE9A1E534}" proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"></comInterfaceExternalProxyStub></assembly>