Hallo Comminity,
ich habe folgendes, zurzeit Programmiere ich ein AddIn für MS Outlook, dafür verwende ich von einem Fremdanbieter einen AddIn Wrapper. Das ganze klappt auch wunderbar, nur habe ich folgendes Problem. Wenn das AddIn Regestriert wurde, kann ich nicht einfach Outlook als externes Startprojekt angeben (Start-Debug->External Programm) und in meinen Code rein zu debuggen. Das ganze funktioniert allerdings wenn ich mich an den Prozess anfüge (Attach To Process).
Nun hatte ich gedacht ich mache mir das ganze einfach indem ich einfach ein Windowsprogramm schreibe das über Proccess Outlook startet. Und via WMI mir ein Event sendet wenn Outlook wirklich da ist. Dann wollte ich mit einfach die Assembly reinladen von dem Outlook AddIn (Assembly.LoadFrom) und dann VS Studio einfach in den Prozess von Outlook einklinken.
Das einklinken funktioniert soweit, zumindest bekomme ich beim Versuch mich einzuklinken in Outlook den Hinweis das ich mich bereits auf dem Prozess befinde. Leider springt mir der Compiler dennoch auf keinen angelegten Breakpoint. Also, irgendwas läuft schief :-)
Vielleicht hat ja jemand eine Idee woran es hapert.
// outlook addin assembly
Assembly info = Assembly.LoadFrom(<Pfadname usw.. + *.dll>);
PropertyData propertyData = e.NewEvent.Properties["TargetInstance"];
if (propertyData != null)
{
ManagementBaseObject mbo = propertyData.Value as ManagementBaseObject;
int id = Convert.ToInt32(mbo["ProcessId"]); // get current process id
_Watcher.Stop(); // stops the wmi watcher
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)Marshal.GetActiveObject("VisualStudio.DTE.8.0");
EnvDTE.Processes procs = dte.Debugger.LocalProcesses;
foreach (EnvDTE80.Process2 p in procs)
{
if (p.ProcessID == id) // check process id
{
p.Attach(); // p.Attach2("Managed");
dte.Debugger.CurrentProcess = p; // attach to Outlook Process
break;
}
}
}
}
Na ja, irgendwie habe ich so das Gefühl das es jetzt nur noch besser werden kann.
Die rote Karte ist so ne Sache, denke da hätte man davor auch mal durchgreifen können.
Aber dafür muntert einen SWR3 Morgens mit „Mir sin die wo gwinne welle!“ wieder auf ;-)
Finde das ganze schon okay - selbst wenn man das ein oder andere umschreibt könnte man kaum was verbessern. Irgendwie musst ja 0x41 0x41 zusammenführen zu 0xAA.
Dann sollte auch meineBindingSource.EndEdit() ohne weiteres gehen.
Ansonsten ist halt DataBinding immer Default DataSourceUpdateMode.OnValidation also so das änderungen erst dann gebunden werden wenn der Focus sich verändert.
Kannst dir auch das EndEdit() spaaren und es wie folgt erledigen:
Hrm, ich glaube am besten kann das Microsoft selbst erklären :-)
*Die kleinen Tricks und Kniffe liegen eigentlich immer bei der Namensgebung.
Steht irgendwo hWnd weist du, das hier ein Handle übergeben musst von z.b. einem Steuerelement, einer Form oder eines Controls usw.
*Wenn du Namen wie hwndCallback siehst, weisst du automatisch, ah hier muss der Funktionszeiger zurückgegeben werden.
*Großgeschriebene Namen wie TODO geben meistens an das es sich um eine Struktur oder ein Enum handelt. Wenn man Groß und Kleingeschriebene Namen ließt wie WindowsMessages weis man das es sich in der Regel nur um Enum’s handelt und nicht um Strukturen.
(* Edit: Eine Faustregel ist das ganze nicht!)
Wenn man sich unsicher ist wo man nun die genauen Strukturen oder Enum’s dann herbekommt und unter www.pinvoke.net nichts findet. So kann man anhand des DLL Namen ermitteln wo man genau nachschauen muss. Die user32.dll ist eine Client-DLL von Windows und somit weis man, ah ich muss für nähere Informationen also in der Windows API Dokumentation nachsehen was genau gebraucht wird. Wenn der Name irgendwie komisch sein sollte oder auf pinvoke nicht auffindbar so weis man das es sich evtl. um eine Fremde API handelt die z.B. dafür verwendet wird irgend etwas anzusteuern. Hier hilft dann die Dokumentation des Fremdanbieters weiter, oder der Kollege der vielleicht diese DLL geschrieben hat.
Natürlich kann es auch sein das beim Import einer DLL plötzlich mal „int hwndCallback“ oder gleich „delegate hwndCallback“ da steht, dennoch bleibt es ein Funktionszeiger – die Schreibweise kann somit also variieren genauso wie der Namen. Dennoch denke ich das in der Regel der Importname aus der Doku wie aus pinvoke in der Regel aussagekräftig genug ist um klar werden zu lassen, was man übergeben muss.
Du kannst die Anzeige auch via nen ToolTip relaisieren, wenn jemand über einen Datensatz der nicht komplett dargestellt wird drüber scroult wird einfach der Tooltext eingeblendet der diesen visualisiert.
Bist dir daher sicher das M12 wirklich in deinem Header drinne steht unter public?
public:
void (*M12)();
Ansonsten schau dir das Project mal genauer an, das sollte das ganze besser aufzeigen. Es muss gehen, irgendwas stimmt da noch nicht - kann auch sein das ich wiedermal blind bin und es einfach nicht sehe
Hrm, die harte Methode wäre den WindowsStyle zu verändern, siehe dazu WIN API GetWindowLong und SetWindowLong.
Eine weitere Möglichkeit wäre eine neue Kalsse zu erstellen von dem gewünschten Control abzuleiten und über SetStyles z.B. die Zeichenroutine selbst in die Hand zu nehmen - das kann man z.B. dann über System.Windows.Forms.VisualStyles lösen.
Wieder ein anderer Weg wäre die WndProc zu überschreiben und via WIN API BeginPaint und EndPaint im der WM_PAINT Methode ebenso das Zeichenverhallten zu verändern - hier wird etwas anders gezeichnet, siehe dazu MSDN.
Dann kann man auch noch den Weg ohne die Zeichenroutine zu beinflussen gehen indem man vom gewünschten Control ableitet und via SetStyles das Mouseverhallten beeinflusst. So das unter umständen einfach der Cursor nicht mehr gesetzt werden darf und kann (da muss man etwas herumexperimentieren).
Aber egal welche Möglichkeiten verwenden möchtest, das Problem daran ist, es kostet einfach Zeit und Geduld und manipuliert eigentlich das Standardverhallten.
Würde wahrscheinlich eher dann ein eigenes Control dafür schreiben.
Ich glaube kaum das Photoshop via Entropie die Daten immer wieder neu visualisiert.
Zumindest wäre das ziemlich komplex auf dauer, für einfache Pinseleien die der Benutzer macht würde ich das ganze noch nachvollziehen können. Aber wenn Effekte rückgängig gemacht werden sollen, kann der Effekt als solches ja nicht nochmals in umkehrvor verwendet werden.
Angenommen der Effekt Weichzeichnen wird verwendet, so kann ich diesen Effekt nicht als umkehrfunktion (Starkzeichnen) Verwenden und das Bild sieht wieder aus wie zuvor.
Das Wort "immer" hätte ich allerdings weglassen sollen - es kommt wirklich darauf an, da stimme ich dir zu.
Da es sich um Anno 1602 handelt ists ja kein Ding zu Antworten ;-)
Bist du dir sicher das die Adresse des Funktionszeigers (0x560264) stimmt?
Ansonsten, hast du überprüft ob der Stack wirklich nur 4 bytes groß ist? - 1.000.000 (2 Dwords) 8 Bytes in den meisten Games...
Ansonsten, schön und sauber - sehe wenn den Fehler nicht :-)
Bei VARIANT ist halt immer blöd ohne dne zugrundeliegend C++ Code nachzusehen wie das SafeArray schlussendlich ausgelesen wird. Eine Kapselung wie m_rcppCommands= new RcppMessage[] { msg }; kommt mir aber spanisch vor, oder hatte der Hersteller das expleziet verlangt?
Wenn das nicht hinhaut denke ich eher das folgende snoch gemeint sein könnte:
Zuerst wurde das Grafische object selectiert die Ansicht wurde serialisiert wie sie unselectiert dann wie sie selectiert aussieht - daher BubelEvent Bevore und After Event. Dannach wird sich die Ansicht gemerkt wie sie vor dem gruppieren aussah, dann wie sie nach dem gruppieren aussieht. Zuletzt wird die Ansicht serialisiert bevor die Gruppierung das schlussendlich auch wieder nur irgend ein object hier vom Typ Array ist vor dem verschieben und im anschluss nach dem verschieben aussieht.
Schreib lieber viele Commands als wenige, das zahlt sich später aus. Lieber mal eine Komposition zuviel als zu wenige.
/PS
Sollte alles eigentlich BubbleEvent heissen.. bin zu Faul das nun zu korrigieren ;-)
1.) Eine einzelne Liste wäre für Undo / Redo ausreichend also sprich das Makro-Command reicht. Stell dir dazu einfach wieder Adobe Phoroshop vor. GUi Technisch würdest du evtl. 5 mal Move-Command sehen und vielleicht 3 mal ein anderes Command usw. Jedes Command würde einzeln dastehen in einer für den Benutzer ersichtlichen und logischen Reihenfolge.
2.) Wenn du jede Aktion mit einer Liste versiehst bräuchtest (Move-Command) sähe das wie folgt aus. Du hättest eine Liste mit allen Command's also Move-Command und andere Commands die du so hast. Wenn man nun Move-Command anklickt sieht man zwar in einer logischen reihenfolge die einzelnen Move-Commands. Aber man würde nicht mehr sehen wurde zuerst Move-Command ausgeführt oder irgend ein andere Command. Hier hätte der Benutzer selber keine Chance mehr zu verstehen was er rückgängig machen müsste um seine z.B. letzte Aktion rückgängig zu machen.
Wenn kein UI Pflegst und kein Undo / Redo direkt verwenden möchtest für den Benutzer ersichtlich its, wäre es egal was du machst - hier käme es darauf an was dein Programm den mit der Liste anstellt. Ansonsten rate ich dir lieber zu Punkt 1.) - denn in den meisten Fällen tut's das allemale und selten muss man innerhalb eines Commands eine einzelne Aktion rückgängig machen bzw. wiederherstellen.
Vorallem wenn eh das ganze zu behandelnde Object serialisierst. Denk dran, eine Singleton wird sogut wie immer beim CommandPattern gebraucht, dort hast du dann auch deine Macro-Liste.
Hrm, beim CommandPattern sollten immer alle Daten Redundant gespeichert werden. Spätestens beim Undo/Redo, wenn dir Adobe Photoshop mit den Aktionen vorstellst, dort hast ja ebenso die Möglichkeit zu sagen ich möchte von Aktion 20 alle Rückgängigmachen bis wieder hin zu aktion 15. Und somit macht es Sinn wirklich alle Daten wie bei dir nun End + Startposition zu merken. Der Witz am CommandPattern ist ja das es so erweitenr kannst wie du Lust hast. Du könntest dir statt nur Punkte wie X und Y vom Start wie Endpunkt zu merken das gesammte Object als solches merken z.B. via Serialisierung. Der Vorteil hierbei wäre, selbst wenn du Vorhast zusätzliche Aktionen einzubauen könntest du beim Undo / Redo direkt auf das gewählte Undo / Redo Command hin und herspringen ohne das irgendwelche Berechnungen anfallen oder Commands die dazwischen lagen / liegen wiederholt ausführen musst.
Bei mir ist es eher ein klares nein.
Natürlich erstelle ich gerne wenn ich viel Zeit habe mal ein kleines Probeprojekt um mir etwas genauer anzusehen, nur ist das eher selten der Fall. Was Litaratur angeht so verhällt sich das bei mir sporadisch, lese gerne und relativ viel - nur nicht eben immer ein Programmierbuch.
Hrm, hatte vor kurzen ein ähnliches Project. Habe das über TAPIEx gelöst und war mit deren Anbindung wirklich zufrieden. Das ganze ist allerdings nicht kostenlose.
Hrm, heimgehen ist eine gute Idee.
Und falls nächste Woche langweile aufkommt, im Forum gibt es immer Suchende die sich über des anderen langweile freuen :o)
Hrm, die Idee ist gut und wirst lachen verwende diese auch Schnueggel. Man kann das ganze weiter treiben indem man hier mit XML arbeitet und von aussen her diese sogar bearbeiten kann und sich bisherige Einstellungen sogar merkt. Nur was ich leider nicht bewerten kann ist dann gleich eine Umsetzung via WPF - habe damit einfach noch keine Erfahrung.
Hrm... ohne WIN API habe ich dir sonst leider keine Idee.
Der andere Weg wäre über einen globalen LowLevelMouse Hook gewesen, hier kann man dann beim MouseMove einfach nen Bild oder Abbild als GostImage zeichnen. Nur ob das Performanter ist als die Lösung von codeProject, bezweifle ich.
Vielleicht kennt jemand ja noch einen reinen .NET Weg - aber ist this.Cursor.Draw() ebenso auf 250px beschränkt?
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr IntPtr_Module, string csProcName);
private delegate void myFunctionDelegate();
private myFunctionDelegate Invoke = MyFunction();
public void DoIt()
{
Invoke();
}
private static myFunctionDelegate MyFunction()
{
IntPtr hMod = GetModuleHandle("CA123A.exe"); // das module handle in der sich die M12 funktion befindet.
IntPtr hFunction = GetProcAddress(hMod, "M12"); // M12 nach deinem code die void* Methode im C++ Code
return Marshal.GetDelegateForFunctionPointer(hFunction, typeof(myFunctionDelegate)) as myFunctionDelegate;
}
Wie gesagt bei deinem Problem kann ich nur via Try & Error an den Fall dran gehen eine "dieser Weg funktioniert garantiert" Lösung kann ich dir nicht geben. Wenn das nicht klappt geb bescheid, dann muss ein anderer Lösungsweg gefunden werden. Also keine übergabe via WndProc oder SendMessage - ich würde dir gerne den Unterschied erklären, leider fehlt mir dafür das KnowHow :o)
Das bezog sich auch nicht auf den Thread sondern nur auf das von JAck30lena gepostete :-)
@spongebob
Okay, das hätte ich zu aller erst auch mal versucht klar wird aber durch die Fehlermeldung dass das nicht alles ist. Die reine übergabe des Funktionszeigers reicht ja nicht aus, nun kommt ja der Fehler den Talla und JAck30lena meinten.
Hrm, versuch mal folgendes hol dir den Funktioszeiger nicht über die WndProc sondern direkt aus dem Fremdmodul, das kannst du über die WIN API GetModuleHandle und den Funktionszeiger via GetProcAddress holen.
Wenn das nicht hinhaut kann man noch nen paar andere Schritte angehen.