|
antonaras wrote: 1.'strcat' : cannot convert parameter 1 from 'class std::basic_string,class std::allocator >' to 'char *
use Obj.C_str();
antonaras wrote: 2.error C2664: 'PutCommandText' : cannot convert parameter 1 from 'class std::basic_string,class std::allocator >' to
'class _bstr_t'
use wrapper _bstr_t
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|
What you really need is a parameterised query. The idea is that you create a parameter, and associate it with the command object.
You can then fill in the value, and run the command. Check out the documentation for CreateParameter.
This is preferred to concatenating the text because it avoids problems with strings containing quotes, and the so-called SQL injection attacks.
Steve S
Developer for hire
|
|
|
|
|
Hey Steve allways appreciate the help (again )
I hope i'm not asking much but can you give me an example
|
|
|
|
|
This isn't pretty, nor is it optimal, but it covers the basics; You'll want to reindent the code, and I do things a little differently, by using raw interfaces when importing.
Where there is a call to doQuery, you can put so UI in there to ask for & validate a query field. This is a bit rough in places, normally I use OLE DB rather than ADO, but it works. You'll need to change the name of the data source (obviously).
The trick is to create the parameter and associate it with the command object. You can then use Execute to get a recordset, and having done that, you can ask the recordset to requery without needing the command object (once you've changed the parameter value. Add a different call to doQuery with a different string below the first one, and you'll see what I mean.
The advantage over straight SQL text building is that in many cases, the SQL needs to be parsed only once, which is handy for complex queries, and in addition, it protects you from some nasty so-and-so from performing a SQL injection attack.
(Yes, it was asking a bit much, but I had a spare 10 minutes at lunchtime[local time])
<br />
#include <windows.h><br />
#include <tchar.h><br />
#include <ole2.h><br />
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" \<br />
no_namespace rename("EOF", "EndOfFile") raw_interfaces_only<br />
#include <stdio.h><br />
#include <conio.h><br />
<br />
<br />
void printRows(_Recordset* pRstTemp)<br />
{<br />
VARIANT_BOOL bEOF;<br />
pRstTemp->MoveFirst();<br />
<br />
pRstTemp->get_EndOfFile(&bEOF);<br />
if (bEOF)<br />
{<br />
_tprintf(_T("\tRecordset empty\n"));<br />
}<br />
else<br />
{<br />
_bstr_t bstrTitle;<br />
_bstr_t bstrType;<br />
<br />
while(!bEOF)<br />
{<br />
FieldsPtr spFields;<br />
FieldPtr spField;<br />
long nFields;<br />
pRstTemp->get_Fields(&spFields);<br />
spFields->get_Count(&nFields);<br />
for(long f = 0; f < nFields; f++)<br />
{<br />
BSTR t = NULL;<br />
<br />
spFields->get_Item(_variant_t(f), &spField);<br />
_variant_t v;<br />
spField->get_Value(&v);<br />
spField->get_Name(&t);<br />
if (v.vt != VT_NULL)<br />
{<br />
v.ChangeType(VT_BSTR);<br />
#ifdef _UNICODE<br />
_tprintf(_T("%20.20s: %s\n"), (LPCWSTR)t, (LPCWSTR)v.bstrVal);<br />
#else<br />
_tprintf(_T("%20.20S: %S\n"), (LPCWSTR)t, (LPCWSTR)v.bstrVal);<br />
#endif<br />
}<br />
else<br />
{<br />
#ifdef _UNICODE<br />
_tprintf(_T("%20.20s: (null)\n"), (LPCWSTR)t);<br />
#else<br />
_tprintf(_T("%20.20S: (null)\n"), (LPCWSTR)t);<br />
#endif<br />
}<br />
SysFreeString(t);<br />
spField = NULL;<br />
}<br />
_tprintf(_T("\n"));<br />
pRstTemp->MoveNext();<br />
pRstTemp->get_EndOfFile(&bEOF);<br />
}<br />
}<br />
}<br />
<br />
void doQuery(_CommandPtr& pCmd, _RecordsetPtr& pRS, _ParameterPtr& pParam, LPCTSTR custid)<br />
{<br />
HRESULT hr;<br />
pParam->put_Value(_variant_t(custid));<br />
if (pRS==NULL)<br />
{<br />
hr = pCmd->Execute(NULL,NULL,0,&pRS);<br />
}<br />
else<br />
{<br />
hr = pRS->Requery(0);<br />
}<br />
if (SUCCEEDED(hr))<br />
{<br />
printRows(pRS);<br />
}<br />
}<br />
<br />
void doSample()<br />
{<br />
HRESULT hr;<br />
_ConnectionPtr spConn;<br />
_CommandPtr spCommand;<br />
_RecordsetPtr spRS;<br />
_ParameterPtr spParam;<br />
ParametersPtr spParamSet;<br />
_variant_t custid;<br />
<br />
hr = spConn.CreateInstance(__uuidof(Connection));<br />
if (SUCCEEDED(hr))<br />
{<br />
_bstr_t empty(_T(""));<br />
_bstr_t sample(_T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=nwind.mdb"));<br />
hr = spConn->Open( sample, empty, empty, adModeUnknown);<br />
if (SUCCEEDED(hr))<br />
{<br />
hr = spCommand.CreateInstance(__uuidof(Command));<br />
if (SUCCEEDED(hr))<br />
{<br />
spCommand->put_CommandText(_bstr_t("SELECT * FROM customers WHERE CustomerID = ?"));<br />
spCommand->put_Prepared(VARIANT_TRUE);<br />
spCommand->putref_ActiveConnection(spConn);<br />
hr = spCommand->Execute(NULL,NULL,adCmdText, &spRS);<br />
hr = spCommand->get_Parameters(&spParamSet);<br />
spParamSet->Refresh();<br />
hr = spCommand->CreateParameter(NULL,adBSTR,adParamInput,NULL,custid,&spParam);<br />
spParamSet->Append(spParam);<br />
<br />
doQuery(spCommand, spRS, spParam, _T("ALFKI"));<br />
}<br />
else<br />
{<br />
_tprintf(_T("Unable to create command [HR=0x%8lX]\n"),hr);<br />
}<br />
spConn->Close();<br />
}<br />
else<br />
{<br />
_tprintf(_T("Unable to open connection [HR=0x%8lX]\n"),hr);<br />
}<br />
}<br />
else<br />
{<br />
_tprintf(_T("Unable to create connection object [HR=0x%8lX]\n"), hr);<br />
}<br />
}<br />
<br />
<br />
int main(int argc, char**argv)<br />
{<br />
if (SUCCEEDED(CoInitialize(NULL)))<br />
{<br />
doSample();<br />
CoUninitialize();<br />
}<br />
return 0;<br />
}
Steve S
Developer for hire
|
|
|
|
|
Try to use a temp string for the query
string token;
token = "SomeName";
string query;
query = "SELECT * FROM Table1 WHERE Name=" + token;
pCommand->CommandText = query.data()
codito ergo sum
|
|
|
|
|
Hey BadKarma thanks for the reply looks like is getting there i used your code and it compiles with no prob
but i get an error at runtime
Error:ΘÆ
Press any key to continue
|
|
|
|
|
strcpy(string,"SELECT * FROM Table1 WHERE Name=?");
strcat( string, token );
-------------
wsprintf(string,"SELECT * FROM Table1 WHERE Name=%s",token);
whitesky
|
|
|
|
|
I've written a VC++ 6.0 app (based on Microsoft's Printmon example) that uses printer notification api's. These work fine for local printers but whenever I try a network printer (\\server\printer name) my application fails with an Invalid Handle from the FindNextPrinterChangeNotification api call. The Printmon example also does this. My client is XP with SP2 and the servers holding the queues are Windows 2000 and Windows 2003, anyone any ideas ?
|
|
|
|
|
If u r using \\server\printer name as a string forget not to include '\' before each '\' , means "\\\\Server\\printer name" should be used.
Appu..
"If you judge people, you have no time to love them."
|
|
|
|
|
|
Printername for network printer is in the correct format, my call to OpenPrinter is successful.
Its the call to FindNextPrinterChangeNotification that is actually failing with an invalid handle.
|
|
|
|
|
Use the Handle returned by OpenPrinter , as the input Handle for FindNextPrinterChangeNotification
Appu..
"If you judge people, you have no time to love them."
|
|
|
|
|
You seem to have missed the point ... I know openprinter returns a handle which is then used by FindFirstPrinterChangeNotification which itself returns a handle which is then used by the FindNextPrinterChangeNotification api. I've written out several items including the handle values, which are correct and don't change between the FindFirst and FindNext calls, but the FindNext call always errors with an invalid handle - but why with network printers ?
|
|
|
|
|
Did u get the answer for this...if yes please post it ...
|
|
|
|
|
Sorry no never got it working, abandoned the project a year or so ago.
|
|
|
|
|
Hey finally got the fix for this...
open windows firewall(run->firewall.cpl)
open advanced tab and check file and printer sharing option
Let me know if you face any problem with this...
|
|
|
|
|
hi,I have got this problem,
The situation is I have close my firewall,
and the printer is a network printer
when I look up the property of the printer, its port is USB002,
so, I don't know how to fix it,
can anyone help?
|
|
|
|
|
P Gibson wrote: ...my application fails with an Invalid Handle from the FindNextPrinterChangeNotification api call.
What does GetLastError() return?
"The largest fire starts but with the smallest spark." - David Crow
|
|
|
|
|
Using the tried and trusted ErrorBox method as follows
void ErrorBox (DWORD dwError, LPCSTR lpString)
{
#define MAX_MSG_BUF_SIZE 512
char *msgBuf;
DWORD cMsgLen;
cMsgLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER | 40,
NULL, dwError,
MAKELANGID(0, SUBLANG_ENGLISH_US),
(LPTSTR) &msgBuf, MAX_MSG_BUF_SIZE,
NULL);
MessageBox( NULL, msgBuf, lpString, MB_OK );
LocalFree( msgBuf );
#undef MAX_MSG_BUF_SIZE
it displays ... each and every time for a network printer !
The handle is invalid.
|
|
|
|
|
Ok, is the call to FindFirstPrinterChangeNotification() fine?
What do the calls to OpenPrinter() and WaitForSingleObject() look like?
"The largest fire starts but with the smallest spark." - David Crow
|
|
|
|
|
here is my code, I have taken out some debug strings, but the printername is valid as are the values of the handles returned. The code has been taken from the Microsoft Printmon example with just a few changes as I am using this in a class, hence the use of 'this'
// setup printer name
strcpy (pPrinterName, this->m_PrinterName);
// open Printer, if access denied return
ZeroMemory (&pd, sizeof (pd));
pd.DesiredAccess = PRINTER_ACCESS_USE;
if((nReturn = OpenPrinter (pPrinterName, &hPrinter, &pd)) == ERROR_ACCESS_DENIED) return FALSE;
// initialize local copy of the printer queue data
ZeroMemory (&Queue, sizeof(Queue));
Queue.Printer.hPrinter = hPrinter;
GetQueue (&Queue);
// prepare for notifications, we want when a job is added, check for an error
hPrinterNotification = FindFirstPrinterChangeNotification (hPrinter, PRINTER_CHANGE_JOB, 0, &NotificationOptions);
if (hPrinterNotification == INVALID_HANDLE_VALUE) return 0;
Queue.Printer.hPrinterNotification = hPrinterNotification;
// loop while we are stilling waiting on Notifications
while (Queue.Printer.hPrinterNotification != INVALID_HANDLE_VALUE)
{
if (WaitForSingleObject (Queue.Printer.hPrinterNotification, INFINITE) == WAIT_OBJECT_0)
{
// get the changes and reset the notification
if (!FindNextPrinterChangeNotification (Queue.Printer.hPrinterNotification, &dwWaitResult, &NotificationOptions, (void **)&pNotification))
{
ErrorBox(GetLastError(), "FindNextPrinterChangeNotification ...failed\r\n");
}
Note also that the Printmon example also fails at the FindNextPrinterChange call with an invalid handle when the printer is a network one, so the error is consistent.
|
|
|
|
|
In c++ and c, use LPCTSTR p = "string" or const TCHAR p[] = "string", which better and why?
|
|
|
|
|
using LPCTSTR, you only have a pointer.
using const TCHAR[], you have a tab, which size is set at the first allocation. so after that, if you affect the tab to another string, it could be truncated or throw an overflow access.
TOXCCT >>> GEII power
[VisualCalc 3.0 updated ][Flags Beginner's Guide new! ]
|
|
|
|
|
I don't find any difference.
Appu..
"If you judge people, you have no time to love them."
|
|
|
|
|
Both of them are creating data at stack memory. I'm not feeling any differnce!!!
SaRath
"D on't blindly follow rules you read somewhere without verifying that it makes sense for your situation!"
|
|
|
|
|