char cmdstr[] = "..\\..\\mysql\\bin\\mysqldump --opt --extended-insert=false --triggers -R --hex-blob --single-transaction -uroot -pxxx --database -d mydatabase > G:\\mydatabase \\mydatabase.sql";
CreateProcess(NULL, cmdstr, NULL, NULL, TRUE, CREATE_NO_WINDOW,NULL, NULL, &st, &pi)),
执行时会说找不到数据库,其实就是'>'不能正确解析的原因,后来把'>'改成了"--result-file=",问题就解决了。但是我在导入时,一样遇到了这样的问题,比如说我要导入的参数数
char cmdstr[] = "..\\..\\mysql\\bin\\mysql -uroot -pxxx mydatabase < G:\\mydatabase\\mydatabase.sql";,
这个在用createprocess()执行后,输出的文本中显示的却是mysql的命令帮助语法,但却根本没导入进去(createprocess本身执行是成功的),但是用system()就没有这个问题,我猜还是由于那个'<'不能正常解析导致的。但是system()会产生一个dos黑框,由于如果数据库比较大,一个黑框老在那,感觉很不爽,请问能否不出现黑框,而且能执行完才往下走的?或者说'>'可以有什么字符串替代的么?先谢谢了~~~~
4 个解决方案
#1
有个对象WScript.Shell,可以隐藏运行框,并一直等待其运行结束
代码大概是:
。。。。
代码大概是:
oo=CreateObject('WScript.Shell')
oo.Run(xxx,0,1) //运行xxx, 并卡住系统, 直到运行结束
。。。。
#2
size_t ExecuteProcess(std::wstring FullPathToExe, std::wstring Parameters, size_t SecondsToWait)
{
size_t iMyCounter = 0, iReturnVal = 0, iPos = 0;
DWORD dwExitCode = 0;
std::wstring sTempStr = L"";
/* - NOTE - You should check here to see if the exe even exists */
/* Add a space to the beginning of the Parameters */
if (Parameters.size() != 0)
{
if (Parameters[0] != L' ')
{
Parameters.insert(0,L" ");
}
}
/* The first parameter needs to be the exe itself */
sTempStr = FullPathToExe;
iPos = sTempStr.find_last_of(L"\\");
sTempStr.erase(0, iPos +1);
Parameters = sTempStr.append(Parameters);
/* CreateProcessW can modify Parameters thus we allocate needed memory */
wchar_t * pwszParam = new wchar_t[Parameters.size() + 1];
if (pwszParam == 0)
{
return 1;
}
const wchar_t* pchrTemp = Parameters.c_str();
wcscpy_s(pwszParam, Parameters.size() + 1, pchrTemp);
/* CreateProcess API initialization */
STARTUPINFOW siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
pwszParam, 0, 0, false,
CREATE_DEFAULT_ERROR_MODE, 0, 0,
&siStartupInfo, &piProcessInfo) != false)
{
/* Watch the process. */
dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, (SecondsToWait * 1000));
}
else
{
/* CreateProcess failed */
iReturnVal = GetLastError();
}
/* Free memory */
delete[]pwszParam;
pwszParam = 0;
/* Release handles */
CloseHandle(piProcessInfo.hProcess);
CloseHandle(piProcessInfo.hThread);
return iReturnVal;
}
#3
@trainee1楼的不太清楚用的是什么语言,但你说会卡系统?就算了,@ACMAIN_CHM 2楼的跟我以前写的差不多,就是把字符变成宽字符了,我把宽字符变成正常的去试了下,发现出错,返回值是5,网上查了一下说是权限问题,仔细核对了下路径什么的全是绝对路径,而且也没错……实在不行只能用system函数了。还有一个奇怪的问题,我单独在dos下执行或在单独在c++builder下把调用system这个命令执行 "..\\..\\mysql\\bin\\mysql -uroot -pxxx mydatabase < G:\\mydatabase\\mydatabase.sql";这条语句执行很快,但是放在服务器程序中,就慢了几倍(在服务器程序中是在线程中执行的),【导出的sql文件大概有200M多,前者执行只需要6-8分钟左右,而后者却要半个小时到50多分钟不等】后来我单独把system(char* cmdstr)这个函数做成动态库调用,也一样执行很长时间,是不是因为在线程中分时间片的原因导致很慢?
附下自己的代码【没有解决重定向的问题】
附下自己的代码【没有解决重定向的问题】
bool CBackupData::ExecSQLCmd(char* cmdstr)
{
WaitForSingleObject(m_hMutex,INFINITE);
STARTUPINFO st;
memset(&st, 0, sizeof(STARTUPINFO));
st.cb = sizeof(STARTUPINFO);
//st.dwFlags = STARTF_USESHOWWINDOW;
//st.wShowWindow = SW_SHOW;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
/*
ostringstream str;
str << gcurdir.c_str() << "\\" << OUTPUT_FILE;
string fileName = str.str();
HANDLE hStdOutput = CreateFile(fileName.c_str(), GENERIC_WRITE, 0, &sa,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
GetStartupInfo(&st);
st.hStdOutput = (HANDLE)hStdOutput;
st.hStdError = (HANDLE)hStdOutput;
*/
st.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
if(CreateProcess(NULL, cmdstr, NULL, NULL, TRUE, CREATE_NO_WINDOW,
NULL, NULL, &st, &pi))
{
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
/*
CloseHandle(hStdOutput);
ostringstream str;
str << gcurdir.c_str() << "\\" << OUTPUT_FILE;
string fileName = str.str();
readFile(fileName.c_str());
*/
}
else
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
cout << (LPCTSTR)lpMsgBuf <<endl;
if(NULL != m_buf)
{
memset(m_buf,0,strlen((LPCTSTR)lpMsgBuf)+1);
memcpy(m_buf,lpMsgBuf,strlen((LPCTSTR)lpMsgBuf)+1);
}
LocalFree( lpMsgBuf );
ReleaseMutex(m_hMutex);
return false;
}
ReleaseMutex(m_hMutex);
return true;
}
#4
后来还是把这个方法弃用了,因为在还原数据库时,没法知道还原的进度和状态,后来改为用C API执行,所有问题都解决了,既能获得还原的进度,还不会跳出黑框……不过有一点需要注意的是在windons下,用C API调用LOAD DATA INFILE时,路径的问题!!!比如说正常代码会这样写:
string sqlcmdstr = "LOAD DATA LOCAL INFILE 'C:\\mytable.txt' INTO TABLE mytable;" ; xx.query(sqlcmdstr.c_str())其中这个\\必须写成四个斜杠'C:\\\\mytable.txt',否则这个LOAD DATA会执行失败【这个问题花了我好久才找到原因的,网上也有这样的问题,但是貌似回答的都不确切,至少在我这行不通】,还有那个C API 执行query的时候,说执行一条语句时,不需要加封号;,但貌似我加进去也没报错;没仔细研究了……
#1
有个对象WScript.Shell,可以隐藏运行框,并一直等待其运行结束
代码大概是:
。。。。
代码大概是:
oo=CreateObject('WScript.Shell')
oo.Run(xxx,0,1) //运行xxx, 并卡住系统, 直到运行结束
。。。。
#2
size_t ExecuteProcess(std::wstring FullPathToExe, std::wstring Parameters, size_t SecondsToWait)
{
size_t iMyCounter = 0, iReturnVal = 0, iPos = 0;
DWORD dwExitCode = 0;
std::wstring sTempStr = L"";
/* - NOTE - You should check here to see if the exe even exists */
/* Add a space to the beginning of the Parameters */
if (Parameters.size() != 0)
{
if (Parameters[0] != L' ')
{
Parameters.insert(0,L" ");
}
}
/* The first parameter needs to be the exe itself */
sTempStr = FullPathToExe;
iPos = sTempStr.find_last_of(L"\\");
sTempStr.erase(0, iPos +1);
Parameters = sTempStr.append(Parameters);
/* CreateProcessW can modify Parameters thus we allocate needed memory */
wchar_t * pwszParam = new wchar_t[Parameters.size() + 1];
if (pwszParam == 0)
{
return 1;
}
const wchar_t* pchrTemp = Parameters.c_str();
wcscpy_s(pwszParam, Parameters.size() + 1, pchrTemp);
/* CreateProcess API initialization */
STARTUPINFOW siStartupInfo;
PROCESS_INFORMATION piProcessInfo;
memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));
siStartupInfo.cb = sizeof(siStartupInfo);
if (CreateProcessW(const_cast<LPCWSTR>(FullPathToExe.c_str()),
pwszParam, 0, 0, false,
CREATE_DEFAULT_ERROR_MODE, 0, 0,
&siStartupInfo, &piProcessInfo) != false)
{
/* Watch the process. */
dwExitCode = WaitForSingleObject(piProcessInfo.hProcess, (SecondsToWait * 1000));
}
else
{
/* CreateProcess failed */
iReturnVal = GetLastError();
}
/* Free memory */
delete[]pwszParam;
pwszParam = 0;
/* Release handles */
CloseHandle(piProcessInfo.hProcess);
CloseHandle(piProcessInfo.hThread);
return iReturnVal;
}
#3
@trainee1楼的不太清楚用的是什么语言,但你说会卡系统?就算了,@ACMAIN_CHM 2楼的跟我以前写的差不多,就是把字符变成宽字符了,我把宽字符变成正常的去试了下,发现出错,返回值是5,网上查了一下说是权限问题,仔细核对了下路径什么的全是绝对路径,而且也没错……实在不行只能用system函数了。还有一个奇怪的问题,我单独在dos下执行或在单独在c++builder下把调用system这个命令执行 "..\\..\\mysql\\bin\\mysql -uroot -pxxx mydatabase < G:\\mydatabase\\mydatabase.sql";这条语句执行很快,但是放在服务器程序中,就慢了几倍(在服务器程序中是在线程中执行的),【导出的sql文件大概有200M多,前者执行只需要6-8分钟左右,而后者却要半个小时到50多分钟不等】后来我单独把system(char* cmdstr)这个函数做成动态库调用,也一样执行很长时间,是不是因为在线程中分时间片的原因导致很慢?
附下自己的代码【没有解决重定向的问题】
附下自己的代码【没有解决重定向的问题】
bool CBackupData::ExecSQLCmd(char* cmdstr)
{
WaitForSingleObject(m_hMutex,INFINITE);
STARTUPINFO st;
memset(&st, 0, sizeof(STARTUPINFO));
st.cb = sizeof(STARTUPINFO);
//st.dwFlags = STARTF_USESHOWWINDOW;
//st.wShowWindow = SW_SHOW;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
/*
ostringstream str;
str << gcurdir.c_str() << "\\" << OUTPUT_FILE;
string fileName = str.str();
HANDLE hStdOutput = CreateFile(fileName.c_str(), GENERIC_WRITE, 0, &sa,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
GetStartupInfo(&st);
st.hStdOutput = (HANDLE)hStdOutput;
st.hStdError = (HANDLE)hStdOutput;
*/
st.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES;
PROCESS_INFORMATION pi;
if(CreateProcess(NULL, cmdstr, NULL, NULL, TRUE, CREATE_NO_WINDOW,
NULL, NULL, &st, &pi))
{
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
/*
CloseHandle(hStdOutput);
ostringstream str;
str << gcurdir.c_str() << "\\" << OUTPUT_FILE;
string fileName = str.str();
readFile(fileName.c_str());
*/
}
else
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
cout << (LPCTSTR)lpMsgBuf <<endl;
if(NULL != m_buf)
{
memset(m_buf,0,strlen((LPCTSTR)lpMsgBuf)+1);
memcpy(m_buf,lpMsgBuf,strlen((LPCTSTR)lpMsgBuf)+1);
}
LocalFree( lpMsgBuf );
ReleaseMutex(m_hMutex);
return false;
}
ReleaseMutex(m_hMutex);
return true;
}
#4
后来还是把这个方法弃用了,因为在还原数据库时,没法知道还原的进度和状态,后来改为用C API执行,所有问题都解决了,既能获得还原的进度,还不会跳出黑框……不过有一点需要注意的是在windons下,用C API调用LOAD DATA INFILE时,路径的问题!!!比如说正常代码会这样写:
string sqlcmdstr = "LOAD DATA LOCAL INFILE 'C:\\mytable.txt' INTO TABLE mytable;" ; xx.query(sqlcmdstr.c_str())其中这个\\必须写成四个斜杠'C:\\\\mytable.txt',否则这个LOAD DATA会执行失败【这个问题花了我好久才找到原因的,网上也有这样的问题,但是貌似回答的都不确切,至少在我这行不通】,还有那个C API 执行query的时候,说执行一条语句时,不需要加封号;,但貌似我加进去也没报错;没仔细研究了……