I'm currently attempting to build a simple C++ program to insert a record into a MS Sql Server database. The code executes and return codes indicate that things technically worked, yet no record is actually getting inserted to the database. I'm at a lose as to what might be causing the issue. Driver maybe?
Originally I intended to use prepared statements and avoid any string copying, but I couldn't seem to get those to work properly. So, to test if anything would happen at all, I build a query as below. Not the best approach and not my intended approach but I can't even seem to get a record inserted to the db.
Return codes do not indicate problems with the connection (please note, I've changed the actual connection information) or even the execution of the query, which leans me towards perhaps needing a commit? Also why I might be inclined to think it is the driver. Thoughts?
Here is the code:
stdafx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
#include <Windows.h>
#include <winnt.h>
#include <sqlext.h>
#include <rpc.h>
#include <iostream>
#pragma comment(lib, "rpcrt4.lib")
And testCamel2Db.cpp
// testCamel2Db.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
INT connectDb(VOID);
int _tmain(int argc, _TCHAR* argv[])
{
connectDb();
return 0;
}
INT connectDb (VOID)
{
RETCODE rc; //ODBC return code
HENV henv; //environment handle
HSTMT hstmt;//statement handle
HDBC hdbc; //connection handle
SQLAllocEnv(&henv);
SQLAllocConnect(henv, &hdbc);
rc = SQLDriverConnect(
hdbc,
NULL,
(unsigned char*)"DRIVER={SQL Server};SERVER=server.name.edu,3433;DATABASE=camel2;UID=username;PWD=password;",
SQL_NTS,
NULL,
0,
NULL,
SQL_DRIVER_COMPLETE);
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
//error handling here
std::cout << "no connection created.";
return 1;
}
//create a uuid
UUID uuid;
UuidCreate(&uuid);
unsigned char* uuidStr;
UuidToStringA(&uuid,&uuidStr);
INT quotedUuidSize = strlen((char*)uuidStr) + 2;
char* quotedUuidStr = new char[quotedUuidSize +1];
memset(quotedUuidStr, 0, sizeof(char) * quotedUuidSize + 1);
strcat(quotedUuidStr, "'");
strcat(quotedUuidStr, (char*)uuidStr);
strcat(quotedUuidStr, "'");
//admin_user variable
LPSTR adminUser;
adminUser = "'Active Directory'";
//build a query
LPSTR sql = "INSERT cw_ResetCheck (ResetUID, AdminUser ) values (";
INT queryStrSize = strlen(sql) + strlen((char*)quotedUuidStr) + strlen(adminUser) + 2;
char* queryStr = new char[queryStrSize + 1];
memset(queryStr, 0, sizeof(char) * (queryStrSize + 1));
strcat(queryStr,sql);
strcat(queryStr,(char*)quotedUuidStr);
strcat(queryStr,",");
strcat(queryStr,adminUser);
strcat(queryStr,")");
std::cout << queryStr << "\n";
rc = SQLAllocStmt(hdbc,&hstmt);
std::cout << uuidStr;
rc = SQLExecDirect(hstmt, (SQLCHAR*)queryStr, SQL_NTS);
if ((rc != SQL_SUCCESS) && (rc != SQL_SUCCESS_WITH_INFO))
{
std::cout << "query failed";
return 1;
}
else
{
std::cout << "uid created: ";
std::cout << uuidStr;
}
//close database
SQLFreeStmt(hstmt,SQL_DROP);
SQLDisconnect(hdbc);
SQLFreeConnect(hdbc);
return 0;
}
Related
I'm new in NSIS and C++.
I write a NSIS plugin to check a license with http request with VS2010.
But the plugin only work on the computers with VS2010 installed.
I guess the reason is the libraries like "ws2_32.lib" is not bundled in the package.
I want the installation package with this plugin worked on the computers without C++ installed.
Is there any idea how to solve it?
Thanks a lot.
Here is my code.
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <WinSock2.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
#include <string.h>
#include <stdio.h>
#include "./../nsis/pluginapi.h"
#include <windows.h>
#include <Wincrypt.h>
#pragma comment(lib,"crypt32")
#pragma comment(lib,"./../nsis/pluginapi-x86-unicode.lib")
#pragma comment(lib, "ws2_32.lib")
void __declspec(dllexport) myFunction(HWND hwndParent, int string_size,
TCHAR *variables, stack_t **stacktop,
extra_parameters *extra)
{
g_hwndParent = hwndParent;
EXDLL_INIT();
//读取输入参数
WCHAR szComponent[256];
popstring(szComponent);
//打印参数
WCHAR buf[1024];
//这里能正确打印出来自NSIS的中文信息。
//wsprintf(buf, L"kagula $0=[%s][szComponent]\n", szComponent);
//MessageBoxW(g_hwndParent, buf, 0, MB_OK);
WCHAR urlComponent[256];
popstring(urlComponent);
//wsprintf(buf, L"kagula $0=[%s][urlComponent]\n", urlComponent);
//MessageBoxW(g_hwndParent, buf, 0, MB_OK);
WCHAR ipComponent[256];
popstring(ipComponent);
WCHAR portComponent[256];
popstring(portComponent);
//准备返回参考
int len = (int)wcslen(szComponent);
int input_len = (int)wcslen(szComponent);
//printf("%d\n", input_len);
//char server_id[256];
//for (int i = 0; i <
char* server_id = wchar2char(szComponent);
printf("%d\n", strlen(server_id));
//char* server_id = new char(256);
//for (int i = 0; i < input_len; i++) {
// server_id[i] = szComponent[i];
//}
//to_narrow(szComponent, server_id, 256);
printf("serid %s", server_id);
//打印参数
char* ret = ""; // 返回Http Response
try
{
// 开始进行socket初始化
WSADATA wData;
::WSAStartup(MAKEWORD(2, 2), &wData);
SOCKET clientSocket = socket(AF_INET, 1, 0);
struct sockaddr_in ServerAddr = {0};
char* m_ip = wchar2char(ipComponent);
int m_port = atoi(wchar2char(portComponent));
char* req = wchar2char(urlComponent);
WCHAR bufchar[3069];
//这里能正确打印出来自NSIS的中文信息。
//wsprintf(bufchar, L"kagula $0=[%s][server_id]\n", char2wchar(server_id));
//MessageBoxW(g_hwndParent, bufchar, 0, MB_OK);
printf("req %s", req);
char* urlSend = (char*) malloc(strlen(req) + strlen(server_id));
strcpy(urlSend, req);
strcat(urlSend, server_id);
//strcat(req, server_id);
printf("req %s", req);
ServerAddr.sin_addr.s_addr = inet_addr(m_ip);
ServerAddr.sin_port = htons(m_port);
ServerAddr.sin_family = AF_INET;
int errNo = connect(clientSocket, (sockaddr*)&ServerAddr, sizeof(ServerAddr));
printf("errNo connect %d \n", errNo);
if(errNo == 0)
{
// "GET /[req] HTTP/1.1\r\n"
// "Connection:Keep-Alive\r\n"
// "Accept-Encoding:gzip, deflate\r\n"
// "Accept-Language:zh-CN,en,*\r\n"
// "User-Agent:Mozilla/5.0\r\n\r\n";
char* cookie = " HTTP/1.1\r\nCookie:16888\r\n\r\n";
// strSend = "GET " + req + strSend;
char* gp = "GET ";
char* strSend = (char*) malloc(strlen(gp) + strlen(cookie) + strlen(urlSend));
strcpy(strSend, gp);
strcat(strSend, urlSend);
strcat(strSend, cookie);
// 发送
errNo = send(clientSocket, strSend, strlen(strSend), 0);
if(errNo > 0)
{
//cout << "发送成功" << endl;
}
else
{
//std::cout << "errNo:" << errNo << std::endl;
printf("errNo:");
// return ret;
}
// 接收
char bufRecv[3069] = {0};
errNo = recv(clientSocket, bufRecv, 3069, 0);
if(errNo > 0)
{
ret = bufRecv;// 如果接收成功,则返回接收的数据内容
}
else
{
// std::cout << "errNo:" << errNo << std::endl;
printf("errNo:");
// return ret;
}
}
else
{
errNo = WSAGetLastError();
// std::cout << "errNo:" << errNo << std::endl;
printf("errNo:");
printf(errNo + "");
}
// socket环境清理
::WSACleanup();
}
catch (...)
{
// return "";
}
printf(ret);
// push back on the stack
TCHAR * tchar;
char* ok_str = "ServerId is OK";
if(strstr(ret, ok_str) == NULL) {
tchar = _T("0");
} else {
tchar = _T("1");
}
for (int i = 0; i < len; ++i) {
printf("%d", i);
szComponent[i] += 1;
}
pushstring(tchar);
}
I guess the reason is the libraries like "ws2_32.lib" is not bundled in the package.
No, that thing is only consumed by Visual C++ linker. In runtime, the corresponding DLL is taken from C:\Windows\System32\ws2_32.dll
Most likely reason is C and C++ runtime DLLs. By default, Visual Studio C++ projects use dynamic linking to these libraries. For an installer plugin, a good way to fix is switch to static C++ runtime. Right click on the project, Configuration properties, C/C++, Code Generation, change the “Runtime Library” setting to Multi-threaded Debug (/MTd) for debug configuration and Multi-threaded (/MT) for release configuration.
P.S. I would recommend a higher-level library for HTTP networking, such as WinHTTP or WinINet. Modern Internet has migrated from http to https.
I'm a green hand coder from China. I met some problem in using the google-geocoding-api, it is correct when I debug with the following code, but there is no response when I use the gennerated .exe file compile in release mode。Cause I am in China,So I can just use the net agent to visit the URL,so I don't kown wheteher it is the problem of net work or the problem of my code. Could someone help me to try the following code to check the exactly problem.
// street_name.cpp :
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <Windows.h>
#include <wininet.h>
using namespace std;
#define MAXBLOCKSIZE 500
#pragma comment (lib, "wininet.lib")
void download(const char*);
int main(int argc, char* argv[]){
const char *cUrl = NULL;
char Url[512];
float lat = 45.798748;
float lng = 126.531115;
sprintf(Url,"https://maps.googleapis.com/maps/api/geocode/xml?latlng=45.797749,126.523811&result_type=route&address_component_type=route&key=AIzaSyC6M3Pbbjdrgtl8QZjuJPK-1JdAJD5oEgA",lat,lng);
cUrl = Url;
download(cUrl);
if (argc > 1)
{
download((const char*)argv[1]);
}
else
{
cout << "Usage: auto-Update url";
}
return 0;
}
/**
*
* #param Url: The target action url
*
*/
void download(const char *Url)
{
HINTERNET hSession = InternetOpenA("RookIE/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
string StreetName;
if (hSession != NULL)
{
HINTERNET handle2 = InternetOpenUrlA(hSession, Url, NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
if (handle2 != NULL)
{
cout << Url << endl;
byte Temp[MAXBLOCKSIZE] = {0};
ULONG Number = 1;
int i = 0;
ofstream ofs("baidu.txt");
if (ofs)
{
while (Number > 0)
{
InternetReadFile(handle2, Temp, MAXBLOCKSIZE - 1, &Number);
string a = string((const char*)Temp,Number);
ofs << a.c_str();
StreetName += a;
}
ofs.close();
}
InternetCloseHandle(handle2);
handle2 = NULL;
}
InternetCloseHandle(hSession);
hSession = NULL;
}
}
If your requests are coming from China, it may be that HTTPS requests are blocked. Try HTTP.
I'm thinking this may be related to https://meta.stackexchange.com/questions/191338/https-problem-when-accessing-stack-overflow-in-china
I'm trying to make a simple client-server program using windows file mapping and that uses semaphores. The clients send to the server 2 numbers, the server computes nr1+nr2 and nr1 * nr2. I tried something but it doesn't even work for 1 client and I want it to work for more clients. Here's the code:
the server:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct {
int nr1;
int nr2;
} Mesaj;
int main(int argc, char** argv) {
Mesaj* mesaj;
HANDLE createSemaphore = CreateSemaphore(NULL, 1, 1, "Semafor");
if (createSemaphore == NULL || createSemaphore == INVALID_HANDLE_VALUE) {
wcout << "Failed to create a semaphore\n";
} else {
wcout << "Created the semaphore\n";
}
HANDLE hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, sizeof(Mesaj), "SharedMemory");
WaitForSingleObject(createSemaphore, INFINITE);
mesaj = (Mesaj*) MapViewOfFile(hMemory, FILE_MAP_READ, 0, 0, sizeof(Mesaj));
printf("The numbers received are: %d, %d\n", mesaj->nr1, mesaj->nr2);
int produs = mesaj->nr1 * mesaj->nr2;
int suma = mesaj->nr1 + mesaj->nr2;
printf("\nSuma numerelor este: %d iar produsul lor este: %d", suma, produs);
ReleaseSemaphore(createSemaphore, 1, NULL);
Sleep(INFINITE);
return 0;
}
the client:
#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct {
int nr1;
int nr2;
} Mesaj;
int main(int argc, char** argv) {
Mesaj* mesaj, *mesaj2;
mesaj2 = (Mesaj*) malloc(sizeof(Mesaj));
HANDLE hMemory = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE,
"SharedMemory");
if (hMemory == NULL) {
wcout << "Error at OpenFileMapping\n";
}
HANDLE openSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS,TRUE,"Semafor");
if(openSemaphore != NULL || openSemaphore != INVALID_HANDLE_VALUE){
wcout<<"the semaphore is opened\n";
}
mesaj2 = (Mesaj*) MapViewOfFile(hMemory, FILE_MAP_WRITE, 0, 0,
sizeof(Mesaj));
int nr1 = 0, nr2 = 0;
printf("Give a number: ");
scanf("%d", &nr1);
printf("Give another number: ");
scanf("%d", &nr2);
mesaj2->nr1 = nr1;
mesaj2->nr2 = nr2;
if (mesaj2 == NULL) {
wcout << "Error\n"
} else {
wcout << "I sent " << mesaj2->nr1 << " and " << mesaj2->nr2 << endl;
}
system("pause");
return 0;
}
What exactly am I doing wrong? How should I work with semaphores?
When I open the server it doesn't wait for the client.
The documentation for CreateSemaphore says
The state of a semaphore object is signaled when its count is greater than zero, and nonsignaled when its count is equal to zero. The lInitialCount parameter specifies the initial count.
You passed lInitialCount=1 when you created the semaphore. and 1 > 0, so the semaphore is signaled and the WaitForSingleObject returns immediately.
You presumably want to create the semaphore with an initial count of 0, so that it does not become signaled until somebody calls ReleaseSemaphore.
I am building a client that:
Should be able to recieve information from both the server and the standart input
Should be able to recieve information from the server without asking, for example when another client sends a message.
To do so I tried using select to monitor both possible inputs.
What happens is that when a keyboard input is monitored I send a message to the client and I expect one back, so there's no problem. But when the server sends an unexpected message nothing happens, and I don't know why. Is using select() the proper way to do so? Is it even possible to use select() without listen()ing?
Here's my code (compileable):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <cstring>
#include <arpa/inet.h>
#include <iostream>
#include <fstream>
#define MAX_CLIENT_NAME 30
#define MAX_TWIT_SIZE 140
#define NUM_OF_ARG 4
#define ERROR -1
#define GREAT_SUCCESS 0
#define OK "OK"
#define EXIT "EXIT"
using std::string;
using std::cerr;
using std::endl;
using std::cout;
string clientName;
int srverfd, numbytes, status, maxSock ;
fd_set inputFdSet; /* Socket file descriptors we want to wake
up for, using select() */
int establishConnection(char * serverAddress,char * port){
if ((srverfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
return ERROR;
}
struct sockaddr_in server;
server.sin_family = AF_INET;
inet_aton(serverAddress, &server.sin_addr);
server.sin_port = htons(atoi(port));
memset(&(server.sin_zero), '\0', 8);
if (connect(srverfd,(const struct sockaddr *)&server,sizeof(struct sockaddr)) == -1) {
perror("connect");
close(srverfd);
return ERROR;
}
maxSock = srverfd;
return GREAT_SUCCESS;
}
const char * getUserTweet(){
string temp;
getline(std::cin,temp);
return temp.c_str();
}
void sendMessage(string message){
if ((numbytes = send(srverfd, message.c_str(), message.length(), 0)) == -1) {
perror("sendMessage");
close(srverfd);
}
cout<<"Message sent: "<< message << endl;
return;
}
const char * getMessage(){
char buf[MAX_TWIT_SIZE];
memset(buf,'\0',MAX_TWIT_SIZE);
if ((numbytes = recv(srverfd, buf, 140, 0)) == -1) {
perror("getMessage");
close(srverfd);
}
string temp = buf;
return temp.c_str();
}
void build_select_list() {
FD_ZERO(&inputFdSet);
FD_SET(srverfd,&inputFdSet);
FD_SET(STDIN_FILENO,&inputFdSet);
if (STDIN_FILENO > maxSock)
maxSock = STDIN_FILENO;
return;
}
void readSocket(fd_set tempfd) {
const char * tweet, * inMessage;
if (FD_ISSET(srverfd,&tempfd)) {
inMessage = getMessage();
cout << inMessage << endl;
}
if (FD_ISSET(STDIN_FILENO,&tempfd)) {
tweet = getUserTweet();
sendMessage(tweet);
inMessage = getMessage();
if (strcmp(inMessage,OK) != 0) {
cout << inMessage << endl;
}
if (strcmp(inMessage,EXIT) == 0) {
return;
}
}
return;
}
int main (int argc, char *argv[] ){
int value;
bool clientON = false;
if(establishConnection(argv[2],argv[3])){
cerr << "usage: failed to make connection" << endl << "exiting..." << endl;
exit(EXIT_FAILURE);
}
cout << "Connected successfully" << endl;
sendMessage("CONNECT "+clientName); //Connect
if(strcmp(getMessage(),OK) == 0){
clientON = true;
}
while(clientON){
build_select_list();
value = select(maxSock, &inputFdSet, NULL, NULL, NULL);
if (value < 0) {
perror("select");
exit(EXIT_FAILURE);
}
if (value == 0) {
continue;
}
else {
readSocket(inputFdSet);
}
}
sendMessage("DISCONNECT");
if(strcmp(getMessage(),OK) == 0){
// do nothing
}
close(srverfd);
return 0;
}
Your select call is invalid. The first parameter must be the highest file descriptor in any of the sets, plus one.
As you have it, an event on srverfd will not "wake up" the select call (unless STDIN_FILENO was somehow less than srverfd, in which case stdin events wouldn't unlock select - but that won't happen in practice).
There are quite a few other problems with your code. (It doesn't really look like C++.)
getUserTweet is unreliable (undefined behavior - temp is destroyed as soon as the function returns, so the char* you return has disappeared by the time its caller will try to use it). Same for getMessage. To remedy that, use std::string everywhere, and only extract the char* when you call into C library functions).
readSocket needlessly copies the FD set (can be expensive).
You should really get rid of all those globals - build one or two classes to encapsulate that state and the networking functions, or something like that.
I decided to use SQLite as it allows to store database into a single file. I think I have managed to do a database with SQLite Database Browser.
How can I read that data in a C/C++ program?
A example using sqlite read:
#include <stdio.h>
#include <sqlite3.h>
#include <string.h>
int main(int argc, char** argv)
{
const char* username = "satyam";
char q[999];
sqlite3* db;
sqlite3_stmt* stmt;
int row = 0;
int bytes;
const unsigned char* text;
if (2 == argc) {
username = argv[1];
}
q[sizeof q - 1] = '\0';
snprintf(
q,
sizeof q - 1,
"SELECT ipaddr FROM items WHERE username = '%s'",
username
);
if (sqlite3_open ("test.db", &db) != SQLITE_OK) {
fprintf(stderr, "Error opening database.\n");
return 2;
}
printf("Query: %s\n", q);
sqlite3_prepare(db, q, sizeof q, &stmt, NULL);
bool done = false;
while (!done) {
printf("In select while\n");
switch (sqlite3_step (stmt)) {
case SQLITE_ROW:
bytes = sqlite3_column_bytes(stmt, 0);
text = sqlite3_column_text(stmt, 1);
printf ("count %d: %s (%d bytes)\n", row, text, bytes);
row++;
break;
case SQLITE_DONE:
done = true;
break;
default:
fprintf(stderr, "Failed.\n");
return 1;
}
}
sqlite3_finalize(stmt);
return 0;
}
How about the 'An Introduction to Sqlite C/C++ Interface', and there is a whole C++ example here on CodeProject.
This is bits of the more full sample,
#include "CppSQLite.h"
#include <ctime>
#include <iostream>
using namespace std;
const char* gszFile = "C:\\test.db";
int main(int argc, char** argv)
{
try
{
int i, fld;
time_t tmStart, tmEnd;
CppSQLiteDB db;
cout << "SQLite Version: " << db.SQLiteVersion() << endl;
db.open(gszFile);
cout << db.execScalar("select count(*) from emp;")
<< " rows in emp table in ";
db.Close();
}
catch (CppSQLiteException& e)
{
cerr << e.errorCode() << ":" << e.errorMessage() << endl;
}
}
One way to do it without additional wrappers
#include <stdio.h>
#include <string>
using std::string;
#include <sstream>
using std::stringstream;
#include "sqlite3.h"
bool find_employee(int _id)
{
bool found = false;
sqlite3* db;
sqlite3_stmt* stmt;
stringstream ss;
// create sql statement string
// if _id is not 0, search for id, otherwise print all IDs
// this can also be achieved with the default sqlite3_bind* utilities
if(_id) { ss << "select * from employees where id = " << _id << ";"; }
else { ss << "select * from employees;"; }
string sql(ss.str());
//the resulting sql statement
printf("sql: %s\n", sql.c_str());
//get link to database object
if(sqlite3_open("data/test.db", &db) != SQLITE_OK) {
printf("ERROR: can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return found;
}
// compile sql statement to binary
if(sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, NULL) != SQLITE_OK) {
printf("ERROR: while compiling sql: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
sqlite3_finalize(stmt);
return found;
}
// execute sql statement, and while there are rows returned, print ID
int ret_code = 0;
while((ret_code = sqlite3_step(stmt)) == SQLITE_ROW) {
printf("TEST: ID = %d\n", sqlite3_column_int(stmt, 0));
found = true;
}
if(ret_code != SQLITE_DONE) {
//this error handling could be done better, but it works
printf("ERROR: while performing sql: %s\n", sqlite3_errmsg(db));
printf("ret_code = %d\n", ret_code);
}
printf("entry %s\n", found ? "found" : "not found");
//release resources
sqlite3_finalize(stmt);
sqlite3_close(db);
return found;
}