您的位置:首页 > 运维架构

调用 SHFileOperation 删除文件夹时返回 1026 (0x402)错误的原因

2010-06-23 12:26 483 查看
如题,昨天遇到一个产品中的清空功能不可用的问题。现象也比较奇怪:当点击界面上的清空历史列表功能的时候,要删除的目标文件夹有时能被删除,有时却不能被删除。经过调试,确认问题出在 SHFileOperation 的调用上,它有时会返回错误码:1026
(0x402
)。先看下这个API的原型:

int SHFileOperation(

LPSHFILEOPSTRUCT lpFileOp

);

其中结构体 LPSHFILEOPSTRUCT 的定义为:

]	typedef struct _SHFILEOPSTRUCT {
HWND hwnd;
UINT wFunc;
LPCTSTR pFrom;
LPCTSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCTSTR lpszProgressTitle;
} SHFILEOPSTRUCT, *LPSHFILEOPSTRUCT;

经过一番谷歌,终于查到原因:调这个 API 时传入的结构体的成员 pFrom 必须以两个 '/0' 字符结尾,而不论有没有指定 fFlags 为
FOF_MULTIDESTFILES![/code]

嗐,原来是这个原因!


原来是 MSDN 没看清楚,写代码时没有多加一个 '/0'。下面是 MSDN 的部分说明:


pFrom

Address of a buffer to specify one or more source file names. These names

must be fully qualified paths. Standard Microsoft MS-DOS wild cards, such as

"*", are permitted in the file-name position. Although this member is declared

as a null-terminated string, it is used as a buffer to hold multiple file names.

Each file name must be terminated by a single NULL character. An additional NULL

character must be appended to the end of the final name to indicate the end of

pFrom


.


下面是一个更正后的 Demo:

#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <iostream>

HRESULT RemoveDir( std::wstring& wstrTargetPath )
{
if (wstrTargetPath.empty() || wstrTargetPath.length() > MAX_PATH)
{
return E_INVALIDARG;
}

/*
* 元素全部初始化为 '/0',保证结尾至少有两个 '/0'
*/
WCHAR	pwszTargetPath[MAX_PATH + 1]	= {0};

::wcsncpy_s(
pwszTargetPath,
_countof(pwszTargetPath),
wstrTargetPath.c_str(),
wstrTargetPath.length()
);

SHFILEOPSTRUCTW FileOp =
{
NULL,
FO_DELETE,
pwszTargetPath,
NULL,
FOF_SILENT | FOF_NOERRORUI | FOF_NOCONFIRMATION,
FALSE,
NULL,
NULL
};

int nRet = ::SHFileOperationW(&FileOp);

return HRESULT_FROM_WIN32(nRet);
}

int _tmain(int argc, _TCHAR* argv[])
{
std::wcout.imbue(std::locale("chs"));

std::wstring	wstrPathToRemove(L"C://Documents and Settings//All Users//Application Data//TestDir");

HRESULT	hRet = RemoveDir( wstrPathToRemove );
if (SUCCEEDED(hRet))
{
std::wcout << L"Remove directory/"" << wstrPathToRemove
<< L"/" succeeded." << std::endl;
}
else
{
std::wcout << L"Remove directory/"" << wstrPathToRemove
<< L"/" failed with error: 0x" << std::hex << hRet << L"." << std::endl;
}
return 0;
}

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐