|
Hello everybody. Recently I coded a client-server application and put it in the start up folder. Everything works perfect except for the log file. The problem is this: When the computer starts up the log file opens fine according to file.is_open(), however, nothing gets written to the file. This only happens on start up. If I open it myself the log file works fine and records everything. But when placed in the startup folder to open itself it fails??? What could be the problem?? This has been annoying me forever and any help would be appreciated. Thanks in advance everybody!!
by the way: using windows XP, VC++ 7
-- modified at 16:01 Tuesday 6th February, 2007
|
|
|
|
|
Are you using the complete path or a relative path when specifying the name of the log file when you open it?
You may be right I may be crazy -- Billy Joel --
Within you lies the power for good, use it!!!
|
|
|
|
|
|
Try using an absolute path instead.
"Approved Workmen Are Not Ashamed" - 2 Timothy 2:15
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|
|
thank you very much works fine now
|
|
|
|
|
Hi,
I am running visual C++ 6.0 MFC. I need to have a secondary thread marshal an interface pointer using CoMarshalInterThreadInterfaceInStream(REFIID riid, LPUNKNOWN pUnk, LPSTREAM* pStm); The interface is used to automate Excel. I want my primary thread to access the interface using CoGetInterfaceAndReleaseStream(LPSTREAM pStm, REFIID riid, LPVOID* ppv); What I need to know is how do I find riid, the reference to the identifier of the interface to be marshaled?
Thanks,
Buck
|
|
|
|
|
AFAIK the REFIID is declared in the header file for the object you are using. I am not familiar in automating Excel but I know there are several articles here on CP that cover the subject. Do a search.
You may be right I may be crazy -- Billy Joel --
Within you lies the power for good, use it!!!
|
|
|
|
|
I have been searching the web for 6 hours and all I can find are references to CoMarshalInterThreadInterfaceStream() and CoGetInterfaceAndReleaseStream() but I cannot find ANY real examples. Where does the COM interface store this REFIID? I need to find out how to get the REFIID so I can pass it into these two functions.
Buck
|
|
|
|
|
If you've #import ed the typelib then you can add the import directive named_guids to the import statement.
Then you will find the IID in the .tlh file.
Otherwise you could marshal the IDispatch interface, unless you're using the v-table part of Excel's dual interfaces. Just use IID_IDispatch as REFIID .
"It's supposed to be hard, otherwise anybody could do it!" - selfquote
|
|
|
|
|
That Just gives me an IID_IDISPATCH undeclared identifier error. I have a thread that I want to be able to cancel and then allow the primary thread to save the excel file and quit the excel application. I searched my entire disk for *.tlh and found no files.
void C65602::RunTestThread()
{
DWORD result;
HRESULT hr;
hr = CoInitialize(NULL);
pTests->pOutput->OpenWorksheet();
pTests->pOutput->OutputMainHeader();
CoMarshalInterThreadInterfaceInStream(IID_IDISPATCH, NULL, &pStream); // IID_IDISPATCH ERROR HERE
... DO THREAD PROCESSING ...
CoUninitialize();
AfxEndThread(0, TRUE);
}
void COutput::OpenWorksheet()
{
m_App.CreateDispatch("Excel.Application");
}
|
|
|
|
|
BuckBrown wrote: That Just gives me an IID_IDISPATCH undeclared identifier error
IID_IDispatch , not IID_IDISPATCH . C/C++ identifiers are case sensitive.
What do you intend to do in your thread and why do you think you need a threading solution?
"It's supposed to be hard, otherwise anybody could do it!" - selfquote
|
|
|
|
|
Sorry yeah,
I have tried to declare this various ways (depending on the sparse examples I'm looking at)
IDispatch dispatch;
IID_IDispatch dispatch;
DISPID dispatch;
LPDISPATCH dispath;
None of them work the way I want. It either compiles and does not work or it fails to compile because it cannot convert IDispatch* to __GUID*. I have tried casting but havent found one yet.
I am looking at trying m_App->lpDispatch->QueryInterface() function. There are a couple of reasons why I want a secondary thread. The secondary thread might take from 10 minutes to over an hour. I wanted a way to allow the user to cancel the test from the same user interface (in this case a tab page) that launched the test. The secondary thread can create and output to an Excel file and then save the file and quit the Excel automation before it dies. If the user clicks on the 'Cancel Test' button I want the primary thread to perform the save and quit. This is why I need to marshal the interface pointer out of the secondary thread and get it from the primary thread.
|
|
|
|
|
Ok...
First, a couple of suggestions and things to consider:
1. I'm a little suspicious about your reasons for using a second thread. You're performing some kind of tests from your secondary thread. How do you know when a test has finished and what the result of the test was? Perhaps this could be done from the primary thread, it depends on how your tests works. I'm not saying that it's wrong, I'm just saying "think about it because it will save you a lot of trouble".
2. To me it would feel more natural if the primary thread was responsible for launching Excel as out-of-process automation server. I suspect that you should get a filename from the user which requires interfacing with the GUI and that shall always be done from the primary thead. It's also a common guideline for each thread that creates COM servers to process messages. In your case the Excel proxy would reside in your secondary thread which I suspect doesn't process messages. If you launched Excel from your primary thread, then you would have the message pump for free.
3. If you continue with your solution to launch Excel from your secondary thread and let the primary thread do the saving stuff to Excel, it won't work if your secondary thread doesn't process messages. You risk facing a nasty deadlock if you try to exit your thread, calling ::CoUninitialize() , before the primary thread has released its interface to Excel. This is because the RPC service, which handles the marshalling between apartment boundaries, sends messages to the proxies and stubs in the different apartments. Sending a message means to wait until the receiving thread has processed the message and if it doesn't your sending thread will deadlock.
Now for how to set up the marshalling and the use of IID_IDispatch :
Declare an IStream* variable in your class. This is going to be used when you're calling ::CoMarshalInterThreadInterfaceInStream() and ::CoGetInterfaceAndReleaseStream() .
The code from which you marshal an interface would look something like this:
HRESULT hr;
hr = ::CoMarshalInterThreadInterfaceInStream( __uuidof( IID_IDispatch ), lpDispatch, &m_stream );
if( FAILED( hr ) )
{
} Now the lpDispatch interface is ready to be fetched from another thread.
The code in the other thread would look something like this:
HRESULT hr;
IDispatch* lpDisp;
hr = ::CoGetInterfaceAndReleaseStream( m_stream, __uuidof( IID_IDispatch ), (void**)&lpDisp );
if( FAILED( hr ) )
{
lpDisp = NULL;
} Now you have a marshalled IDispatch interface.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote
|
|
|
|
|
Thanks for the input. I have printed it off for my binder. The __uuidof cast is completely alien to me. In the meantime I have decided to try this with a UI thread. The reason I'm trying to do this with a thread is basically to learn how to use threads. So far I have not been very successful at it. So now I have a user interface thread but it has a few problems of its own when it needs to display a dialog box (application crashes). I will post this problem as something new.
Thanks again.
Buck
|
|
|
|
|
|
I want to create an application that has 5 dialog type windows in an SDI format. I need the dialog tabs so that the user can click on the different dialog window tab. Furthermore, I can not have any two dialog boxes visible at any one time.
Using the project wizard, I chose an SDI application and created 5 dialog boxes. I used InitDialog to maximize each Window.
Unfortunately, only the active dialog window shows. I can't see the other four windows in a tab-type style.
What am I doing wrong?
|
|
|
|
|
I'm not sure, but see if this[^] sectin helps you.
|
|
|
|
|
You could also use a CDialog based application and insert a CPropoertySheet as the main window.
Hope this helps.
|
|
|
|
|
Make your view derived from CFormView and add a tab control to it.
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Hopefully somebody can help me with this problem. I am fairly new with socket connection. I know you guys will want to see some code but unfortunately this is hard to do as my code is on a classified system. I would prefer not to have to type all the necessary code. However if I have to I will.
I have a server-client socket connect and I use CSocket. Once the connection is made, the server sends 168-byte message to the client once per second. In the client OnReceive function I read the data and then write it to a file. In the OnIdle function of the client I also check if the connection with the server is still up by sending a one-byte message to the server. My problem is that it works for a while and then the client OnReceive stops being called by the framework.
Using debugging I know for a fact that the server is still sending the 168-byte messages every seconds without any errors. I also know that the client is still sending the one-byte message to the server and the server is still receiving it. Both programs seem to be working just fine except for the fact that the OnReceive is no longer being called and therefore I am no longer writing data to the file.
Anybody can help me? Thanks!
BTW it never stops at the same place. I can sometimes receive 2K but other times I can receive a lot more. The most I got was 94,168 bytes.
-- modified at 13:41 Tuesday 6th February, 2007
jpyp
|
|
|
|
|
Hmmm sockets have been around for 24 years and you're using CSocket - classified socket code?
Just teasin.
Anyway, is the protocol TCP?
If you are using OnIdle(), what are you returning from it?
Does it perform better if you move the mouse around occasionally?
Mark
|
|
|
|
|
One other question - Are you pausing your app's main (user interface) thread anywhere, with
Sleep() or a loop? This will prevent the necessary message handling by CSocket which it relies
on to make the OnReceive() call.
Mark
|
|
|
|
|
|
Cool! That's a good one
When you go to higher tranfer rates I'd recommend using CAsyncSocket and/or Sockets APIs and using
WSAEventSelect instead of WSAAsyncSelect. Much better performance and you have complete control
over the events. You can either
a) recv() until there's no more data and go back to waiting for an FD_READ event, which will
occur when more data is in the socket's receive buffer. Or...
b) recv() a certain amount of bytes and go back to waiting for an FD_READ event. If more bytes
are available for receiving then the FD_READ event is set immediately after the last recv() call.
Thank you for the update!
Mark
|
|
|
|
|
The basic advice is that you should make exactly one single call to Receive (which calls the underlying winsock recv() function) from inside your OnReceive function (which the MFC framework calls in response to an FD_READ notification).
This advice can't be found in the MFC documentation, either for CSocket or for CAsnycSocket.
It's found, however, in the documentation for the underlying Winsock functions. For example, see the documentation for WSAAsyncSelect() (which is the Winsock function that causes Windows-style messages to be posted to your application from the network stack) at http://msdn2.microsoft.com/en-us/library/ms741540.aspx[^], which includes this quote:
MSDN at WSAASyncSelect wrote: With these semantics, an application need not read all available data in response to an FD_READ message — a single recv in response to each FD_READ message is appropriate. If an application issues multiple recv calls in response to a single FD_READ, it can receive multiple FD_READ messages. Such an application can require disabling FD_READ messages before starting the recv calls by calling WSAAsyncSelect with the FD_READ event not set.
The point of this is to suggest that you get closer to the Winsock API when you start programming for high-rate transfers. There a a few dozen of these "gotcha's" that you don't learn/know about when using the MFC classes, particularly the CSocket class. Personally, I would avoid CSocket. CAsyncSocket is fine, since it's reasonably close to the Winsock API, but you still need to understand the underlying API if you expect your program to work correctly.
Mike
|
|
|
|