执行一个文件,等待其结束后将其删除 VC++

fengwenqi 2009-02-11 02:59:32
各位朋友:
最近我遇到一个问题,就是选择一个文件将其打开,等打开的文件关闭后再将这个文件删除。实在不知道怎么办?我也想了一些方案,但总是不完美。用VC++开发。
第一个方案:
用ShellExecuteEx来执行。但总是不行,这样会有一个后果是什么呢?一个png或bmp的文件没办法打开。
代码如下:

SHELLEXECUTEINFO appInfo;
ZeroMemory(&appInfo, sizeof(SHELLEXECUTEINFO));
appInfo.cbSize = sizeof(SHELLEXECUTEINFO);
appInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
appInfo.lpVerb = L"open";
appInfo.lpFile = lpFilePath.c_str();
appInfo.nShow = SW_SHOWDEFAULT;

// open the decrypted file
BOOL bResult = ShellExecuteEx(&appInfo);
if ( bResult )
{
if ( NULL != appInfo.hProcess )
{
DWORD dwRes = WaitForSingleObject(appInfo.hProcess, INFINITE);
CloseHandle(appInfo.hProcess);
}
}
// delete the destination file which temporary decrypted
deleteFiles(lpFilePath, FALSE);


这样会有问题,appInfo.hProcess 如果为NULL的话,那么程序就不会等待。而ShellExecuteEx的appInfo.hProcess 有可能为NULL,所以这种方式就会存在问题。比如一个.png, .bmp文件就没办法。对于.png, .bmp文件,是打开了的,由于等待不起作用,继续往下执行,就会把文件删除,因此就会说找不到图片。

第二种方案:
根据文件名的后缀去读注册表,找到这个文件关联的打开方式。即到shell\command下的打开方式,再行成命令行commandline,创建一个进程。代码如下:
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
STARTUPINFO si = {sizeof(si)};

BOOL bResult = CreateProcess(NULL,
chCommandLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);

if ( !bResult )
{
DWORD dwErrorCode = GetLastError();
FPString str(L"Create Process failed");
str.append(getErrorCodeString(dwErrorCode));
MessageBoxW(NULL, str.c_str(), L"Error", MB_OK | MB_ICONERROR);
}

WaitForSingleObject(pi.hProcess, INFINITE);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

// delete the destination file which temporary decrypted
deleteFiles(lpFileInfos, FALSE);


这会有个问题,.png, .bmp的命令行是一个DLL,如:%systemroot%\system32\rundll32.exe "%programfiles%\windows photo gallery\photoviewer.dll", imageview_fullscreen %1 就样创建进程就会失败,而打开方式是EXE的没问题,如WORD等。

朋友们,遇到过这个问题的帮给个建议!小弟不胜感激!
...全文
283 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
梧桐168 2009-02-12
  • 打赏
  • 举报
回复
了解一下
KeSummer 2009-02-12
  • 打赏
  • 举报
回复
咳咳~~LZ没认真看我的回复。。
marrco2005 2009-02-12
  • 打赏
  • 举报
回复
mark
fengwenqi 2009-02-12
  • 打赏
  • 举报
回复
用ShellExecuteEx打开也会有一个问题,比如打开一个WORD文件,如果已经有一个WORD文件打开了,再去用ShellExecuteEx打开的话,它的确能打开这个文件,但是它的进程名柄得不到,即hProcess是NULL,所以用WaitForSingleObject就会不能等到。所以,程序就不会等待,就会立马去执行下面的程序。
fengwenqi 2009-02-12
  • 打赏
  • 举报
回复
我是楼主,这个问题我终于解决了,其实我离成功只差一步了,但就是没想到。
CreateProcess中的命令行,也就是第二个参数中,里面不论是EXE还是DLL,不能含有环境变量的值,应该是EXE或DLL有绝对路径,而从注册表中读出的值是有环境变量的,如%systemroot%\system32\rundll32.exe "%programfiles%\windows photo gallery\photoviewer.dll", imageview_fullscreen %1。所以,就要把环境变量的值转换成绝对路径。
怎么转换呢?
Window已经给我们准备好了的,调用API ExpandEnvironmentStrings(),其原型如下:

DWORD WINAPI ExpandEnvironmentStrings(
__in LPCTSTR lpSrc,
__out LPTSTR lpDst,
__in DWORD nSize
);

具体用法请参见MSDN
如上面的字符串为列,转换后的字符串就成了
c:windows\system32\rundll32.exe C:\Program Files\windows photo gallery\photoviewer.dll", imageview_fullscreen %1,这样就是绝对路径了。
%1是什么呢,那就是要执行文件的路径,把%1换成要打开的文件的路径(这里也是绝对路径),这里还有一个小技巧,就是:

wstring strCommandLine; //它的值就是命令行字符串
INT pos = (INT)strCommandLine.find(L"%1");
if ( -1 != pos )
{
strCommandLine.replace(pos, 2, strDestFilePath); //strDestFilePath是要文件的路径类型是wstring
}
else
{
strCommandLine.append(L" \"").append(lpFileInfos->m_sDestFileInfo.m_szDestFilePath).append(L"\"");
}


这样再CreateProcess

PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
STARTUPINFO si = {sizeof(si)};

BOOL bResult = CreateProcess(NULL,
chCommandLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi);

if ( !bResult )
{
DWORD dwErrorCode = GetLastError();
FPString str(L"Create Process failed");
str.append(getErrorCodeString(dwErrorCode));
MessageBoxW(NULL, str.c_str(), L"Error", MB_OK | MB_ICONERROR);
}

WaitForSingleObject(pi.hProcess, INFINITE);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

// delete the destination file which temporary decrypted
deleteFiles(lpFileInfos, FALSE);

这样WaitForSingleObject(pi.hProcess, INFINITE);就可以成功等待了。
KeSummer 2009-02-11
  • 打赏
  • 举报
回复
你这样测试一下:
先用ShellExcute打开,
然后使用hFile = CreateFile(lpFileName, FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0);
CloseHanlde(hFile);

上面的意思是,当系统关闭该文件的所有句柄的时候,删除文件。

15,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧