|
Amit Dey wrote:
I intend to write an article on CP with such headers and with some of my sample code snippets. It's as yet in the works, and I'm on it.
Do it if you feel like doing it. That's will be certainly welcome especially if you add custom outlook express toolbar techniques, but you don't need to feel entitled to produce anything only as a consequence of our discussion.
Amit Dey wrote:
which month YOU are not publishing anything heavyweight
Sadly, I have never won any competition, so I don't think I would prevent you from winning anything anyway.
|
|
|
|
|
What I understand is first find the Window whose classname = "ThorBrowserWndClass" - Outlook Express 4 main window
"Ath_Note" - each new message you create or read OE is this class
"Outlook Express Browser Class" - main OE window for all ver.
Then you subclass the windows WindowProc. The XXXPluginInfo calls save and store information with regards to your your plugin information - toolbar/menu that is implemented in a dll(__declspec(dllexport)!!).
But please tell us more as how to specifically add toolband items?
I have tried using some very old code here on CP, that specifically drills down the OE window. Using Spy++ you could see that you need to use FindWindow() and FindWindowEx() API's to find-
Outlook Express Browser Class
|
SizeableRebar
|
RebarWindow32(this is the parent band?)
|
3 ToolbarWindow' s - i.e. OE's menu,toolband/rebarband/statusbar.
But although I can get OE's main band, any addition to the band(as in Nick Hodapp's rebarband code on CP) does not show a new toolbar button or menu next to the last item, as expected.
Please show us the way!
Hush,hush...
thought I heard you call my name now.
Kula Shaker.
Amit Dey
Latest articles at CP - PocketPC New menu
Office addin
|
|
|
|
|
What does you addin do? if you need any of Outlook Express's functionality, then the SDK might be of help.
|
|
|
|
|
I am trying to programatically get the ProcessID for a running COM+ application. I am using Windows 2000 (COM+ 1.0) so there is no ApplicationInstances object in the COM Admin library to use, but Component Services in Windows 2000 somehow gets the Process ID anyway. I have been looking all over in the MSDN Library, the web, and microsoft's site trying to find out how to retrieve this. I can get the application's name (just like you can see it in Component Services) and through the same administration object i can get the GUID. What I need is a way to get the actual Process ID of the DLLHOST.EXE that is associated with a specific running instance. I am hoping there is some fairly easy way to do this using mostly API Calls, but I haven't been able to come up with anything. Any help would be greatly appreciated. Thanks.
|
|
|
|
|
UPDATE: I just found a command line utility that will give the command line of any running process, given its ProcessID. Using the command line, you can see the switch given to DLLHOST.EXE which looks like this:
/ProcessID:{CLSID_HERE}
which can be matched up to the Key property of the Application. The problem now, is that there is no source code with this utlity I found. Does anyone know how it might work? It seems like it is making calles to OpenProcess, CreateRemoteThread, etc.
|
|
|
|
|
MSDN sample "Taking a Snapshot and Viewing Processes"
|
|
|
|
|
Thanks Alex, but I don't need help in getting a list of processes. I needed help in takign a process ID and amtching it a COM+ Application name. I've found the source code for that program I spoek of though, and I no longer need help. Thanks anyway.
|
|
|
|
|
I've got a COM+ DLL running through ASP pipes in IIS. I can currently debug it using a VB app which calls it, but I would like to debug it through it's real environment. Anyone knows how this can be done?
|
|
|
|
|
Assuming you are using Component Services of Win2k platform and that your component is a C++ component developed in VC++ 6.0, go to package properties, Advanced tab, check the "Launch in debugger" checkbox under Debugging, and as soon as your dll gets loaded, the debugger (VC++) will launch.
As soon as it launches, you have to press F5 (Run) for yourself, or else a timeout will occur and COM+ will think your component failed to initialize.
After you press F5, you can open the source files of your component, insert a breakpoint, make another call in your component, and debug as you would normally do.
Hope my assumptions are right...
|
|
|
|
|
yes, your assumptions are corrent. Thank you. This really helped. Now that I'm able to step into the code, I'm trying to catch the event which happens when you 'shut down' the COM+ application from the component manager.
From what I've seen, no code is called at all. The process just stops, which naturally prevents me to do any log flushing or memory cleanup.
Any ideas?
|
|
|
|
|
Destructors are always called. Why not use them?
|
|
|
|
|
Well, they aren't called when you 'shut down' the component from COM+. Had they been called - my life would have been easier (to a certain extent)
|
|
|
|
|
Does anyone know of any good referances for writing a file system monitor in VC++ 6.0. I would like to have the same functionality as the one in dot net.
Thanks in Advance
Nick
Forever Developing
|
|
|
|
|
I have an ATL DLL wriite in VC++....and i usng that DLL in a vb project....the problem is that first the dll was working as desired but not now....so i want debug the code and step into the code of the DLL ....can somebody suggest me a solutions.
Deepak Sharma;)
|
|
|
|
|
Place debug build DLL, run VB host. Go into visualStudio build >start Debug> Attach to process, select host process. Load source code place break point.
|
|
|
|
|
Set Break point in your VC++ code. Goto Project-Settings-Debug - Set Executable for Debug session to VB6.exe. Go.
|
|
|
|
|
What I would like to do is create instance of "MSWC.BrowserType". Something similiar to vanilla Com....
CCOmBSTR ProgID(L"MSWC.BrowserType");
hr = ::CLSIDFromString(ProgID, &clsid);
if( FAILED(hr) )
{
hr = ::CLSIDFromProgID(ProgID, &clsid);
if( FAILED(hr) ) return hr;
}
hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IDispatch, (LPVOID *)ppVal);
//At this moment returns 0x80040154
if (SUCCEEDED(hr))
|
|
|
|
|
Scenario: Application0 creates an instance of Application1, which in turn creates an instance of Application2. However, sometimes Application2 does not support the interface Application1 wants to use. The HRESULT returned from CreateInstance() will then indicate "No such interface supported".
How do I (in Application0) find out the name of the interface that caused the error?
Cheers,
Fredrik
"Felix qui potuit rerum cognoscere causas."
|
|
|
|
|
I'm writing a windowless ActiveX control using MFC & VC 6 to perform background ZModem file xfers for a FoxPro 7 app. I'm using Mark Nelson's ("Serial Communications Developer's Guide") Win32 serial library. For a test mechanism, I run 2 instances of the program on the same computer (simulating a modem connection) with 2 serial ports connected via a null modem cable.
Once the control connects to it's test "modem", each instance of the control starts another background thread so that when no file transfer is taking place, the control periodically checks to see if the other end of the phone line is trying to send a file. I would like to fire events up to the FoxPro client so that the client knows when it's receiving a file, finished receiving a file, an error occured, etc.
Events fired from the main thread of the control work without a problem. As long as I don't fire events from within my secondary thread, everything works fine. A FoxPro client never sees events fired from with the secondary thread; a VB client crashes with an access violation when the secondary thread fires an event.
Does anyone have an idea why this is happening? Any help is appreciated.
|
|
|
|
|
Ya, you meet the monster called Marshalling
It's for longer description, but in short words, VB (not only VB of course) expect that you will fire events in the same thread your component was created. This is because your component is probably marked as using Apartment Thread Model.
In case you need to fire events from the secondary thread, you need to marshall the pointer to the VB event callback interface.
As a starter the
CoMarshalInterThreadInterfaceInStream function might help. Or article in MSDN named In-Process Marshaling Helpers
In short - the CoMarshall... packages the interface to the stream in a first thread, you transfer the stream pointer to second thread and demarshall here - retrievnig the correct callback interface.
If you are sure that your component will not run in some old win95 you can look also for using the GIT (Global Interface Table).
For this I would start in help with IGlobalInterfaceTable documentation.
The difference between is that CoMarshal... is useful only when you need to marshall the interface once. Once you retrieve the interface back, the stream became useless.
GIT allows you marshall once, demarshall more times.
If you have more Q, don't hesitate to ask.
|
|
|
|
|
Thanks. I had an epiphany last night that that's where I should be looking. I don't understand all the details yet, but I will. Thanks again!!!
|
|
|
|
|
I have wrote a COM to wrap around registry api. This code can be compiled but it crashed VB while I calling this method. Because I'm new to C++, I don't know much about its datatype conversion. I think the problem should be in RegOpenKeyEx or RegQueryValueEx calling. Can anybody give me the solution.
STDMETHODIMP CoRegistry::GetKey(BSTR sKeyFolder, BSTR sKeyName, BSTR* sKeyValue) {
USES_CONVERSION;
HKEY hKey;
CComBSTR bstrKeyFolder;
bstrKeyFolder = L"SOFTWARE\\";
bstrKeyFolder.AppendBSTR(sKeyFolder);
LPBYTE pRegData = NULL;
unsigned long* lpLength;
*lpLength = 255;
if (ERROR_SUCCESS == RegOpenKeyEx (HKEY_LOCAL_MACHINE, OLE2T(bstrKeyFolder), 0, KEY_ALL_ACCESS, &hKey)) {
if (ERROR_SUCCESS == RegQueryValueEx(hKey, OLE2T(sKeyName), 0, (unsigned long*)REG_SZ, pRegData, lpLength)) {
*sKeyValue = SysAllocString(L"helo"); //this is just for test
RegCloseKey(hKey);
return S_OK;
} else {
RegCloseKey(hKey);
return S_FALSE;
}
} else {
RegCloseKey (hKey);
return S_FALSE;
}
}
Thanks
|
|
|
|
|
Vorrarit Luengwattanakij wrote:
if (ERROR_SUCCESS == RegQueryValueEx(hKey, OLE2T(sKeyName), 0, (unsigned long*)REG_SZ, pRegData, lpLength)) {
*sKeyValue = SysAllocString(L"helo"); //this is just for test
These are the sources of your problem
1. "(unsigned long*)REG_SZ" translates to memory address of 0x00000001, writing to it will create memory access violation
What you meant to do
DWORD dwType = REG_SZ;
.... RegQueryValueEx(hKey, OLE2T(sKeyName), 0, &dwType .....
2. The following is similar, your assign value to memory though uninitialized pointer
Vorrarit Luengwattanakij wrote:
unsigned long* lpLength;
*lpLength = 255;
Solution is similar as well
DWORD dwSize = 255;
.... RegQueryValueEx(...., &dwSize) .....
3. The buffer you pass should be allocated by you to the size of #2
Vorrarit Luengwattanakij wrote:
LPBYTE pRegData = NULL;
BYTE pRegData[255];
P.S. You really should read something on pointers and memory allocation.
|
|
|
|
|
Thank you very much. Those DWORD, LPBYTE, LPTSTR datatypes made me nervous. When reading about C, C++ books, they mostly teach about char*, int*. I would be grateful, if you can provide some sources of information about them.
|
|
|
|
|
DWORD and others described pretty well in MSDN. The truth is they confuse many people. I am using F12 when I do not know what it stands for; it is very handy feature of VS.
|
|
|
|