目标:我正在尝试将一些文件从我的客户端发送到服务器。我正在使用" rsync"用于传输数据。我正在使用CreateProcess APi并传递rsync路径和参数。
肯定案例:当我从本地驱动器发送数据时,例如" C:"是我安装Windows的地方,上面的方法正常工作并传输数据。
问题:当我尝试发送映射驱动器(共享网络驱动器)的数据时。 CreateProcess完成但我得到的错误是rsync无法找到该文件。 相同的rsync命令,当我在命令提示符下运行时,所有文件都成功传输,没有任何错误,但在使用CreateProcess传输文件时失败。
代码:
int CreateRsyncProcess(const wchar_t * ptrCommand)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
SECURITY_ATTRIBUTES sap,sat,sao;
HANDLE out;
DWORD pwExit;
//init the STARTUPINFO struct
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
wstring cmd = L"";
cmd.append(ptrCommand);
//proc sec attributes
sap.nLength=sizeof(SECURITY_ATTRIBUTES);
sap.lpSecurityDescriptor= NULL;
sap.bInheritHandle=1;
//thread sec attributes
sat.nLength=sizeof(SECURITY_ATTRIBUTES);
sat.lpSecurityDescriptor= NULL;
sat.bInheritHandle=1;
//create the proc
if(!CreateProcess(NULL,(LPWSTR)cmd.c_str(),&sap,&sat,1,CREATE_NO_WINDOW,NULL,NULL,&si,&pi))
{
DWORD err = GetLastError();
if(out != INVALID_HANDLE_VALUE)
CloseHandle(out);
return 1;
}
//wait till the proc ends
WaitForSingleObject(pi.hProcess,INFINITE);
GetExitCodeProcess(pi.hProcess,&pwExit);
//close all
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
if(out != INVALID_HANDLE_VALUE)
CloseHandle(out);
TerminateProcess(pi.hProcess,0);
return pwExit;
}
Rsync Cmd : " C:\ Program Files \ cwRsync \ bin \ rsync.exe" -cvriHPDkREL --no-implied-dirs --stats -e'" C:\ Program Files \ cwRsync \ bin \ ssh" -o StrictHostKeyChecking = no -i" C:\ Program Files \ cwRsync \ bin \ rsync-key"' " / cygdrive / Z / 64位" user@server.com:~ / 6a90c592-2b3b-4088-8942-2106776c863a /
是否因为某些与安全相关的问题或权限问题而发生了CreateProcess或其他一些事情? 请帮忙,因为我被困在这上面。
由于
编辑::这在正常流程中运行良好,但是当我在服务中运行它时会失败。所以基本上现在的问题是服务没有访问网络共享。有没有解决方法呢?
答案 0 :(得分:4)
映射驱动器是每个会话 - 隔离会话中的服务无法访问用户会话中的映射驱动器。您需要在服务会话中映射驱动器,或使用UNC路径(而不是映射的驱动器号),并让服务用户访问共享。
答案 1 :(得分:1)
由于您显然正在运行服务,因此您可能需要加载环境才能访问映射文件夹。
像这样。
DWORD dwIdCurrentSession = 0xFFFFFFFF;
WTS_SESSION_INFO* pSessionInfo = NULL;
DWORD dwSessionsCount = 0;
if(WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pSessionInfo, &dwSessionsCount))
{
for(int i=0; i<(int)dwSessionsCount; i++)
{
WTS_SESSION_INFO &si = pSessionInfo[i];
if(si.State == WTSActive)
{
dwIdCurrentSession = si.SessionId;
break;
}
}
WTSFreeMemory(pSessionInfo);
}
if(dwIdCurrentSession != 0xFFFFFFFF)
{
HANDLE hLoggedOnUserToken = NULL;
// Get Session User Token
if(WTSQueryUserToken(dwIdCurrentSession, &hLoggedOnUserToken))
{
LPVOID lpEnviroment = NULL;
if(CreateEnvironmentBlock(&lpEnviroment, hLoggedOnUserToken, false))
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Create Process
if(CreateProcessAsUser(hLoggedOnUserToken,
NULL,
(LPWSTR)cmd.c_str(),
NULL,
NULL,
FALSE,
CREATE_UNICODE_ENVIRONMENT,
lpEnviroment,
NULL,
&si,
&pi )
)
{
// Wait for finish......
// Clean up
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
DestroyEnvironmentBlock(lpEnviroment);
}
CloseHandle(hLoggedOnUserToken);
}
}
答案 2 :(得分:0)
您使用的是哪种特定操作系统,例如Windows 7 32位,Windows 7 64位等?此外,您是否启用了UAC?如果您确实启用了UAC,则以管理员身份运行应用程序时问题是否会消失。
根据您对这些问题的回答,我可能会提供进一步的帮助。我不得不做一些研究。
目前,如果UAC确实是您的问题,我唯一的建议是您调查使用ShellExecuteEx的可能性。在Riding the Vista UAC elevator, up and down找到的RunElevated函数可能对您有用。为方便起见,我将在此处包含该功能。
BOOL RunElevated(
HWND hwnd, LPCTSTR pszPath,
LPCTSTR pszParameters = NULL, LPCTSTR pszDirectory = NULL)
{
SHELLEXECUTEINFO shex;
memset( &shex, 0, sizeof( shex) );
shex.cbSize = sizeof(SHELLEXECUTEINFO);
shex.fMask = 0;
shex.hwnd = hwnd;
shex.lpVerb = _T("runas");
shex.lpFile = pszPath;
shex.lpParameters = pszParameters;
shex.lpDirectory = pszDirectory;
shex.nShow = SW_NORMAL;
return ::ShellExecuteEx(&shex);
}
如果不能使用ShellExecuteEx,您还可以尝试Vista UAC: The Definitive Guide处的CreateProcessElevated函数。