COM не может правильно маршалировать BSTR с управляемого сервера на собственный клиент - PullRequest
3 голосов
/ 01 января 2012

Я борюсь со сценарием, где у меня есть управляемый интерфейс, предоставляемый через COM и используемый собственным клиентом. Мне удалось выделить проблему, и она сводится к тому, что строка во время выполнения взаимодействия неправильно распределяет строку, чтобы смоделировать и воспроизвести эту проблему. Я создал небольшой проект, который выглядит следующим образом:

Сервер:

[ComVisible(true)]
[Guid("5AF8A86E-B129-4FA0-8B6D-E9DF52DFDD84")]
public interface IUrlSync
{
    void GetUrl(
        [MarshalAs(UnmanagedType.BStr)] [Out] out string url
        );
}

[ComVisible(true)]
[Guid("5AF8A86E-B129-4FA0-8B6D-E9DF52DFDD85")]
public class Urlsync : IUrlSync
{
    private const string AddressHolderPath = "url.txt";

    public Urlsync()
    {
        // nothing
    }

    public void GetUrl(out string url)
    {
        url = File.Exists(AddressHolderPath) ? 
            File.ReadAllText(AddressHolderPath) : null;
    }
}

после компиляции этого класса и выполнения regasm + gacutil / i, я построил этот маленький

Собственный клиент:

#include <Windows.h>
#import "../comstr/bin/release/comstr.tlb"

int main(int argc, char* argv[])
{
    CoInitialize(NULL); {

        BSTR bstr;
        HRESULT hr = S_OK;

        comstr::IUrlSyncPtr sync(__uuidof(comstr::Urlsync));
        hr = sync->GetUrl(&bstr);

    } CoUninitialize();
    return 0;
}

И здесь значение в hr равно S_OK, а bstr равно NULL (0x000000).

Чтобы убедиться, что проблема связана с самой сортировкой, я построил

управляемый клиент:

Это вызывает класс UrlSync из другой сборки:

        string bstr;
        comstr.IUrlSync sync = new comstr.Urlsync();

        sync.GetUrl(out bstr);
        Console.WriteLine("the url is: {0}", bstr);

и я получаю ожидаемую строку. чего мне здесь не хватает?

1 Ответ

2 голосов
/ 04 января 2012

Я собрал ваши примеры программ и обнаружил, что они действительно работают, как и ожидалось. Однако есть некоторые проблемы с вашей программой.

Если файл не существует, вы фактически получаете ответ null , с которым вы в настоящее время сталкиваетесь. Может ли это быть так? Учтите, что папка времени выполнения может отличаться от управляемого клиента, созданного вами в качестве дополнительного теста.

Вы можете просто просмотреть оба проекта в отладчике, чтобы увидеть, что происходит.

Код маршаллера, сгенерированный оператором # import , генерирует _com_error исключений, которые вы не перехватываете.

Надеюсь, это поможет.

...