如何调用命令而不出现dos界面

时间:2022-09-02 22:30:49
在做数据库备份和还原的问题,导入导出时,用system函数调用mysqldump命令和mysql命令进行导出导入都能生效,但是由于调用system时,会出现dos界面,我现在不想让那个dos界面出现,同时又能知道何时结束,system()是执行完后,再往下执行,但貌似ShellExecute, WinExec都是异步执行的,也即是说不管命令有没有执行完成,程序都会往下走,最后只能用createprocess函数调用了,可是对这个createprocess调用时,貌似对‘>’ ‘<’这样的符号不支持,比如说直接 使用
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的时候,说执行一条语句时,不需要加封号;,但貌似我加进去也没报错;没仔细研究了……