반응형
출처: http://yamoe.tistory.com/218
윈도우에서 폴더 삭제시 비어있는 폴더가 아닌 경우
일일히 폴더 안의 파일을 삭제해줘야 하는데 (DeleteFile후에 RemoveDirectory)
쉘을 사용할 경우 한번에 삭제할 수 있다.
(어떤 사람들은 system("삭제명령")을 쓰라는 얘기도 있는데 이건 너무한 것 같다.)
이 쉘 함수가 SHFileOperation()으로 파일 및 폴더의 삭제, 복사, 리네임 등 flag에 따라 많은 일을 해준다.
(옵션에 따라 휴지통에 지울 수 도 있다.)
문제는 Vista 이후 부터는 IFileOperation 를 사용하길 권장하고 있으며
실제로 Windows 7에서 SHFileOperation()을 사용할 경우 삭제시 파일을 못찾겠다는 둥 오동작을 한다.
결국 여러 WIndows OS 버전을 만족 시킬려면 윈도우 버전에 따라 SHFileOperation()를 사용할지
IFileOperation()를 사용할지 선택적으로 동작하도록 해줘야 한다.
Vista 전의 OS에선 SHFileOperation()을 통해 Recursive한 디렉토리 삭제 샘플
Vista 부터 이후 OS에선 IFileOperation()을 통해 Recursive한 디렉토리 삭제 샘플
주의 1. XP에서 SHFileOperation와 IFileOperation가 모두 구현된 상태에서 실행할 경우
만약, 두 함수를 구현한 후 XP에서 실행시
윈도우에서 폴더 삭제시 비어있는 폴더가 아닌 경우
일일히 폴더 안의 파일을 삭제해줘야 하는데 (DeleteFile후에 RemoveDirectory)
쉘을 사용할 경우 한번에 삭제할 수 있다.
(어떤 사람들은 system("삭제명령")을 쓰라는 얘기도 있는데 이건 너무한 것 같다.)
이 쉘 함수가 SHFileOperation()으로 파일 및 폴더의 삭제, 복사, 리네임 등 flag에 따라 많은 일을 해준다.
(옵션에 따라 휴지통에 지울 수 도 있다.)
문제는 Vista 이후 부터는 IFileOperation 를 사용하길 권장하고 있으며
실제로 Windows 7에서 SHFileOperation()을 사용할 경우 삭제시 파일을 못찾겠다는 둥 오동작을 한다.
결국 여러 WIndows OS 버전을 만족 시킬려면 윈도우 버전에 따라 SHFileOperation()를 사용할지
IFileOperation()를 사용할지 선택적으로 동작하도록 해줘야 한다.
Vista 전의 OS에선 SHFileOperation()을 통해 Recursive한 디렉토리 삭제 샘플
123456789101112131415161718192021222324252627282930313233bool
CCommonUtil::RemoveUseShellUnderVista(_tstring& filename,
bool
useRecycleBin =
true
)
{
// 파일명 끝에 \0\0 이 있어야 정상동작.
// 그렇지 않은 경우 SHFileOperation()는 1026을 돌려준다.
_tstring from = filename;
from.resize(filename.size() + 2);
from += _T(
"\0\0"
);
SHFILEOPSTRUCT shFileOpStruct = {0,};
shFileOpStruct.hwnd = NULL;
shFileOpStruct.wFunc = FO_DELETE;
shFileOpStruct.pFrom = from.c_str();
shFileOpStruct.pTo = NULL;
shFileOpStruct.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
shFileOpStruct.fAnyOperationsAborted = FALSE;
shFileOpStruct.hNameMappings = NULL;
shFileOpStruct.lpszProgressTitle = NULL;
if
( useRecycleBin )
// 휴지통에 넣기
{
shFileOpStruct.fFlags |= FOF_ALLOWUNDO;
}
int
ret = SHFileOperation(&shFileOpStruct);
if
( ret == 0 )
{
return
true
;
}
else
{
printf
(
"FAILED SHFileOperation[%d]\n"
, ret);
return
false
;
}
}
Vista 부터 이후 OS에선 IFileOperation()을 통해 Recursive한 디렉토리 삭제 샘플
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758#include "Shobjidl.h"
bool
CCommonUtil::RemoveUseShellSinceVista(_tstring& filename,
bool
useRecycleBin =
true
)
{
bool
ret =
false
;
const
TCHAR
* pFrom = NULL;
#ifdef UNICODE
pFrom = filename.c_str();
#else
USES_CONVERSION;
pFrom = A2W(filename.c_str());
#endif
IFileOperation* pfo;
HRESULT
hr;
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if
(SUCCEEDED(hr))
{
HRESULT
hr = CoCreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pfo));
if
(SUCCEEDED(hr))
{
DWORD
flags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI;
if
( useRecycleBin ) { flags |= FOF_ALLOWUNDO; }
// 휴지통에 넣기
hr = pfo->SetOperationFlags(flags);
if
(SUCCEEDED(hr))
{
IShellItem *psiFrom = NULL;
hr = SHCreateItemFromParsingName(pFrom, NULL, IID_PPV_ARGS(&psiFrom));
if
(SUCCEEDED(hr))
{
if
(SUCCEEDED(hr))
{
hr = pfo->DeleteItem(psiFrom, NULL);
if
(SUCCEEDED(hr))
printf
(
"success\n"
);
else
printf
(
"fail\n"
);
}
psiFrom->Release();
}
if
(SUCCEEDED(hr))
{
hr = pfo->PerformOperations();
if
(SUCCEEDED(hr))
{
ret =
true
;
}
}
}
pfo->Release();
}
}
CoUninitialize();
return
ret;
}
주의 1. XP에서 SHFileOperation와 IFileOperation가 모두 구현된 상태에서 실행할 경우
만약, 두 함수를 구현한 후 XP에서 실행시
"프로시저 시작 지점 SHCreateItemFromParsingName을(를) DLL SHELL32.dll에서 찾을 수 없습니다."
에러가 발생한다.
해당 함수가 Vista 이후의 shell32.dll 부터 있는 것이기 때문인데
현재 "프로젝트 속성 > 링커 > 입력 > 지연 로드된 DLL" 에 shell32.dll 를 등록하면 된다.
주의 2. 휴지통에 넣는 기능은 네트워크 드라이브에 있는 파일을 지울땐 적용되지 않는다.
일단 확인한것은 네트워크 드라이브로 연결된 하드의 파일/폴더 삭제시엔 휴지통으로 들어가지 않는다.
로컬 파일이 아니기 때문에 복원문제가 복잡하고 보장할 수 없기 때문으로 생각되기 때문에 당연한 듯 하다.
이런 경우도 복원이 보장되야 한다면 휴지통 기능을 직접 구현해야 하겠다.
추가로..
부록 1. 현재 어떤 윈도우 버전(타입)인지 구하는 함수
해당 함수가 Vista 이후의 shell32.dll 부터 있는 것이기 때문인데
현재 "프로젝트 속성 > 링커 > 입력 > 지연 로드된 DLL" 에 shell32.dll 를 등록하면 된다.
주의 2. 휴지통에 넣는 기능은 네트워크 드라이브에 있는 파일을 지울땐 적용되지 않는다.
일단 확인한것은 네트워크 드라이브로 연결된 하드의 파일/폴더 삭제시엔 휴지통으로 들어가지 않는다.
로컬 파일이 아니기 때문에 복원문제가 복잡하고 보장할 수 없기 때문으로 생각되기 때문에 당연한 듯 하다.
이런 경우도 복원이 보장되야 한다면 휴지통 기능을 직접 구현해야 하겠다.
추가로..
부록 1. 현재 어떤 윈도우 버전(타입)인지 구하는 함수
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081int
GetWindowsType(
void
)
{
/*
return value :
-1 : 버전얻기 실패
1 : Windows 95,
2 : Windows 98,
3 : Windows ME,
4 : Windows NT,
5 : Windows 2000,
6 : Windows XP,
7 : Windows 2003,
8 : Windows Vista, 2008
9 : Windows 7, 2008 R2
*/
int
nVersion= -1;
OSVERSIONINFOEX osvi = {0,};
BOOL
version_ex_flag = 0;
osvi.dwOSVersionInfoSize =
sizeof
(OSVERSIONINFOEX);
if
( !(version_ex_flag = GetVersionEx((OSVERSIONINFO *)&osvi)) )
{
osvi.dwOSVersionInfoSize =
sizeof
(OSVERSIONINFO);
if
( !GetVersionEx((OSVERSIONINFO *)&osvi) )
return
-1;
}
switch
(osvi.dwPlatformId)
{
case
VER_PLATFORM_WIN32_WINDOWS:
// 윈도우즈 9x 기반의 운영체제인 경우
{
if
( osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 0 )
{
nVersion = 1;
// Windows 95
}
else
if
(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 10)
{
nVersion = 2;
// Windows 98
}
else
if
(osvi.dwMajorVersion == 4 && osvi.dwMinorVersion == 90)
{
nVersion = 3;
// Windows ME
}
}
break
;
case
VER_PLATFORM_WIN32_NT:
// NT 기술 기반의 운영체제인 경우
{
if
( osvi.dwMajorVersion <= 4 )
{
nVersion = 4;
// Windows NT
}
else
if
( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
{
nVersion = 5;
//Windows 2000
}
else
if
(version_ex_flag)
{
if
( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
nVersion = 6;
// Windows XP
}
else
if
( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
nVersion = 7;
// Windows 2003
}
else
if
( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
{
nVersion = 8;
// Windows Vista, 2008
}
else
if
( osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
{
nVersion = 9;
// WIndows7, 2008 R2
}
}
}
break
;
}
return
nVersion;
}
반응형
'Study > MFC' 카테고리의 다른 글
CStdioFile로 파일을 읽어 들일때 한글 깨짐현상... (0) | 2011.09.28 |
---|---|
Format 자리수 출력 및 소수점 자리수 반올림 (0) | 2011.09.28 |
[MFC] 파일 드래그 앤 드롭 기능... (0) | 2011.09.28 |
리스트 컨트롤에서 드래그 방지~ (0) | 2011.09.28 |
MFC 파일 입출력 (0) | 2011.09.28 |
댓글