Foarte cool: All Programs /Â Accessories / Snipping Tool. Adio Ctrl-Print Screen, paste in Paint(.NET).
Â
Foarte cool: All Programs /Â Accessories / Snipping Tool. Adio Ctrl-Print Screen, paste in Paint(.NET).
Â
Probabil cei care programeaza in .NET forms de ceva vreme se lovesc frecvent de problema invocarii unei metode a unui control, dintr-un thread altul decat cel care este owner-ul controlului. Nu intru in detaliile problemei, care coboara destul de jos la cozi de mesaje per thread, handle-uri windows si altele;
Solutia cel mai des intalnita este: se face un delegate cu semnatura metodei de invocat, se verifica daca este contextul threadului corect cu Control.IsInvokeRequired, si daca nu, atunci se apeleaza metoda prin Control.Invoke, cu delegate-ul definit anterior.
In timp devine “obositor” si mai ales la proiecte mari, definitia cate unui delegate pentru fiecare metoda posibila. O solutie la “oboseala” ar putea fi urmatoarea (mai putin cateva try – catch blocks 😉 :
class CrossThreadHelper
{
   private delegate Object CallMethodProxyDelegate(Control ctrl, String strMethod, object[] arguments);
    private static Object CallMethodProxy(Control ctrl, String strMethod, object[] arguments)
   {
       MethodInfo method;
       method = ctrl.GetType().GetMethod(strMethod);
       return method.Invoke(arguments);
    }
   public static Object CallMethod(Control ctrl, String strMethod, params object[] arguments)
   {
       if(ctrl.InvokeRequired)
       {
            Delegate = new CallMethodProxyDelegate(CallMethodProxy);
            Object[] newArgs = new Object[3];
            newArgs[0] = ctrl;
             newArgs[1] = strMethod;
            newArgs[2] = arguments;
            return ctrl.Invoke(del, newArgs);
        }
        return CallMethodProxy(ctrl, strMethod, arguments);
    }
}
Exemplu:
CrossThreadHelper.CallMethod(this.frmProgress, “Close”);
Â
Cateodata e util (povestea lui “de ce” e prea lunga) sa se intercepteze apelurile care se fac intr-un server COM DLL 3rd party. Una dintre posibilele solutii la aceasta problema urmeaza:
(voi scurta detaliile, presupunand ca oricum daca nu stiti cum sa ajungeti aici, nu v-ati pus problema interceptiei COM anyway ).
1. New project, ATL project.
2. Cu ajutorul object viewerului, inspectati DLL-ul care va intereseaza; veti avea in COM Object Viewer IDL-ul serverului vizat. Copiati-l in proiectul nou.
3. Adaugati un obiect COM (simple COM object), care va implementa interfata/interfetele care va intereseaza.
4. Nu uitati sa actualizati resursele registry (rgs) cu UUID-urile din IDL-ul “pastat”.
5. Metodele FinalConstruct si Final Release din obiectul COM adaugat la punctul 3, ar putea arata asa:
(IMyInterface este interfata care se intercepteaza):
HMODULE m_hOriginalModule; // handle la DLL-ul interceptat
CComPtr
 HRESULT FinalConstruct()
 {
//Â incarca modulul de interceptat
  m_hOriginalModule = CoLoadLibrary(_T(“
  if(m_hOriginalModule != NULL)
  {
// obtine ptr la IClassFactory
   CComPtr
   DllGetClassObjectFn fn = (DllGetClassObjectFn)GetProcAddress(m_hOriginalModule, “DllGetClassObject”);
   if(fn != NULL)
   {
// apel DllGetClassObject in modulul interceptat, pentru a obtine IClassFactory-ulÂ
    HRESULT hRes = fn(CLSID_MyInterfaceCoClass, IID_IClassFactory, (LPVOID *)&pFactory); Â
    if(FAILED(hRes))
    {
     return hRes;
    }
 // apel CreateInstance pentru a obtine o interfata in implementarea originala
    hRes = pFactory->CreateInstance(NULL, IID_IMyInterface, (LPVOID *)&m_pOriginalInterface);
    if(FAILED(hRes))
    {
     return hRes;
    }
   } Â
  }
 Â
  return S_OK;
 }
 void FinalRelease()
 {
  if(m_hOriginalModule != NULL)
  {
// release inainte de FreeLibrary
   m_pOriginalInterface.Release();
   CoFreeLibrary(m_hOriginalModule);
  }
 }
// se poate rescrie functia InternalQueryInterface pentru a loga ce apeluri QI se fac Â
static HRESULT InternalQueryInterface(void *pThis, const ATL::_ATL_INTMAP_ENTRY *pEntries, const IID &iid, void **ppvObject)
 {
  // log the thing
  HRESULT hRes = CComObjectRootBase::InternalQueryInterface(pThis, pEntries, iid, ppvObject);
  CLog log;
  log.Write(“QI: {%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x} returned=%08x\r\n”,
   iid.Data1, iid.Data2, iid.Data3, iid.Data4[0], iid.Data4[1], iid.Data4[2], iid.Data4[3],
   iid.Data4[4], iid.Data4[5], iid.Data4[6], iid.Data4[7], hRes);
  return hRes;
 }
// se pot rescrie metodele din IMyInterface si loga parametrii
HRESULT MyMethod1(…. )
{
   // log params
   HRESULT hRes = m_pOriginalInterface->MyMethod1(…);
   // log hRes, out params
   return hRes;
}
… etc.
Am gasit ceva timp pentru un post scurt. In ultima vreme am fost destul de ocupat, ceea ce oarecum justifica pauza indelungata. Cu ce m-am ocupat si de ce, sper ca voi apuca sa scriu 🙂
Ma enerveaza mai nou post-urile cu link spam, care incep sa se indeseasca… E vreo solutie pentru wordpress ?
Â
un articol care mi-a cazut in mana http://www.tgdaily.com/2007/02/02/romania_gates_piracy_good/. O fi si asta un punct de vedere :)Â
Another view on the same thing: http://apcmag.com/5254/thanks_for_letting_us_pirate