Помогите с реализацией IEnumString для ОРС сервера на С#
От: Phaust  
Дата: 08.10.08 18:22
Оценка:
Пишу ОРС (COM out of proc) сервер на С#. Возникла проблеммы с реализацией интерфейса IEnumString. Класс реализующий IEnumString выглядит следующим
образом:
 class EnumString : IEnumString
    {
        public List<string> lStr;
        private int currentpos;

        public EnumString()
        {
            lStr=new List<string>();
            currentpos = 0;
        }
       
        public int Next(int celt, [OutAttribute] string[] rgelt, IntPtr pceltFetched)
        {
            int i = 0;
            List<string> ResultList = new List<string>();
            while ((i < celt) && (currentpos < lStr.Count))
            {
                ResultList.Add(lStr[currentpos]);
                i++;
                currentpos++;
            }
            GC.KeepAlive(ResultList);
            rgelt = ResultList.ToArray();
            Marshal.StructureToPtr(i, pceltFetched, false);
            return (i == celt) ? HRESULTS.S_OK : HRESULTS.S_FALSE;
        }

        public int Skip(int celt)
        {
            if (currentpos + celt <= lStr.Count)
            {
                currentpos += celt;
                return HRESULTS.S_OK;
            }
            else
            {
                currentpos = lStr.Count;
                return HRESULTS.S_FALSE;
            }
        }

        public void Reset()
        {
            currentpos = 0;
        }
        public void Clone(out IEnumString ppenum)
        {
            throw new System.NotImplementedException();
        }
        public void Add(string newMember)
        {
            lStr.Add(newMember);
        }
        public bool Remove(string s)
        {
            return lStr.Remove(s);
        }
    }

На стороне клиента я работаю с ним следующим образом
g_pIOPCBrowse->QueryOrganization(&o);
        if(o == OPC_NS_HIERARCHIAL)
        {
        
        hr = g_pIOPCBrowse->BrowseOPCItemIDs(OPC_FLAT, L""/*NULL*/, VT_EMPTY, 0, &pEnumString);
        }
        else
        {
        hr = g_pIOPCBrowse->BrowseOPCItemIDs(OPC_FLAT, L""/*NULL*/, VT_EMPTY, 0, &pEnumString);
        }
        if(FAILED(hr))
        {

            Log->AddString(_T("Error: BrowseOPCItemIDs()"));
        }

        if(hr == S_OK)
        {
            LPOLESTR pszName = NULL;
            LPOLESTR pszTMP = NULL;
            ULONG count = 0;
        
            Log->AddString(_T(""));
            Log->AddString(_T("There are following items on the server:"));

            while((hr = pEnumString->Next(1, &pszName, &count)) == S_OK)
            {
                

                g_pIOPCBrowse->GetItemID(pszName,&pszTMP);
                swprintf(lnItem.data.wszName,100,_T("%s"),pszTMP);

            if(!strcmp(sz3,".")) strcpy(sz3,"VT_EMPTY");
            if(!stricmp(sz3,"VT_I2")) lnItem.data.vt=VT_I2;//TestItem[nTestItem].vt = VT_I2;
            else if(!stricmp(sz3,"VT_I4")) lnItem.data.vt=VT_I4;//TestItem[nTestItem].vt = VT_I4;
              else if(!stricmp(sz3,"VT_EMPTY")) lnItem.data.vt=VT_EMPTY;//TestItem[nTestItem].vt = VT_EMPTY;
              else if(!stricmp(sz3,"VT_R4")) lnItem.data.vt=VT_R4;//TestItem[nTestItem].vt = VT_R4;
              else if(!stricmp(sz3,"VT_R8")) lnItem.data.vt=VT_R8;//TestItem[nTestItem].vt = VT_R8;
              else if(!stricmp(sz3,"VT_BOOL")) lnItem.data.vt=VT_BOOL;//TestItem[nTestItem].vt = VT_BOOL;
              else
              {
                  Log->AddString(_T("Error: valid types: VT_EMPTY, VT_I2, VT_I4, VT_R4, VT_R8, VT_BOOL"));
                     continue;
              }
              ItemDef.szAccessPath = L"";;
              ItemDef.szItemID = lnItem.data.wszName;//TestItem[nTestItem].wszName;
              ItemDef.bActive = TRUE;
              ItemDef.hClient = g_dwClientHandle++;
              ItemDef.dwBlobSize = 0;
              ItemDef.pBlob = NULL;
              ItemDef.vtRequestedDataType = lnItem.data.vt;//TestItem[nTestItem].vt;
              lnItem.data.hClient=ItemDef.hClient;

              hr = g_pIOPCItemMgt->AddItems(1, &ItemDef, &pItemResult, &pErrors);
              if(FAILED(hr))
              {
                    Log->AddString(_T("Error: AddItem()"));
                    continue;
              }
              hr = S_OK;
              if(FAILED(pErrors[0]))
              {

                    Log->AddString(_T("Error: AddItem() item"));
                    continue;
              }
              lnItem.data.hServer = pItemResult->hServer;
              lnItem.data.vt = pItemResult->vtCanonicalDataType;
              nTestItem++;

              ::CoTaskMemFree(pItemResult);
              ::CoTaskMemFree(pErrors);


                lData.insertAtBack(lnItem);
                count_elements_spisok++;
                ::CoTaskMemFree(pszName);
                i++;
            }
            pEnumString->Release();
        }

В итоге,в методе Next в pszName содержиться указатеь 0x00000000. Уже голову себе сломал в чем тут дело,в дебагере видно что Next на сервере вызываеться,все проходит нормально,в count потом содержиться 1,то есть все нормально передаеться,а вот со строкой проблеммы. Помогите решить эту проблемму.
com c# ienumstring
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.