【发布时间】:2019-11-17 19:29:20
【问题描述】:
我正在使用 WinAPI 编写 C++ 控制台程序。该程序适用于文件和目录。程序启动如下:
app -R -1 "掩码"
(例如,"D: \ Work \*")。
-R是递归目录遍历,-1 - 输出有关文件的信息(创建日期、大小、属性)。
完整程序代码:
LIBSPEC BOOL ConsolePrompt(LPCTSTR, LPTSTR, DWORD, BOOL);
LIBSPEC BOOL PrintStrings(HANDLE, ...);
LIBSPEC BOOL PrintMsg(HANDLE, LPCTSTR);
LIBSPEC VOID ReportError(LPCTSTR, DWORD, BOOL);
BOOL TraverseDirectory(LPCTSTR, DWORD, LPBOOL);
DWORD FileType(LPWIN32_FIND_DATA);
BOOL ProcessItem(LPWIN32_FIND_DATA, DWORD, LPBOOL);
DWORD Options(int argc, LPCTSTR argv[], LPCTSTR OptStr, ...) {
va_list pFlagList;
LPBOOL pFlag;
int iFlag = 0, iArg;
va_start(pFlagList, OptStr);
while ((pFlag = va_arg(pFlagList, LPBOOL)) != NULL && iFlag < (int)_tcslen(OptStr)) {
*pFlag = FALSE;
for (iArg = 1; !(*pFlag) && iArg < argc && argv[iArg][0] == '-'; iArg++)
*pFlag = memchr(argv[iArg], OptStr[iFlag], _tcslen(argv[iArg])) != NULL;
iFlag++;
}
va_end(pFlagList);
for (iArg = 1; iArg < argc && argv[iArg][0] == '-'; iArg++);
return iArg;
}
void pr_err(int code) {
setlocale(LC_ALL, "Russian");
if (code == 3) {
printf("Файл с указанным названием по указанному пути не найден.");
}
else if (code == 5) {
printf("Операция отклонена. Возможны следующие причины: \n");
printf("Копируемый файл защищен от копирования, скрыт или используется операционной системой.\n");
printf("В целевой директории стоит запрет на запись файлов.\n");
}
else if (code == 20) {
printf("Устройство не найдено.\n");
}
else if (code == 123) {
printf("Указано некорректное название для файла или директории. Возможно были использованы запрещенные символы.\n");
}
}
static void PrintAttributes(DWORD Attrs)
{
setlocale(LC_ALL, "Russian");
if (Attrs == INVALID_FILE_ATTRIBUTES)
{
printf(" Ошибка чтения атрибутов\n");
}
else
{
printf(" \nАтрибуты: ");
if (Attrs & FILE_ATTRIBUTE_ARCHIVE)
{
printf("A ");
}
if (Attrs & FILE_ATTRIBUTE_COMPRESSED)
{
printf("C ");
}
if (Attrs & FILE_ATTRIBUTE_DIRECTORY)
{
printf("D ");
}
if (Attrs & FILE_ATTRIBUTE_HIDDEN)
{
printf("H ");
}
if (Attrs & FILE_ATTRIBUTE_READONLY)
{
printf("R ");
}
printf("\n");
}
}
int _tmain(int argc, LPCTSTR argv[]) {
setlocale(LC_ALL, "Russian");
BOOL Flags[MAX_OPTIONS], ok = TRUE;
TCHAR PathName[buffsize + 1], CurrPath[buffsize + 1];
LPCTSTR pFileName;
int i, FileIndex;
FileIndex = Options(argc, argv, _T("R1"), &Flags[0], &Flags[1], &Flags[2], NULL);
GetCurrentDirectory(buffsize, CurrPath);
printf("argc = %d Index = %d\n", argc, FileIndex);
if (argc < FileIndex + 1) {
printf("Поиск в текущей директории:\n (%s)\n", CurrPath);
ok = TraverseDirectory(_T("*"), MAX_OPTIONS, Flags);
}
else {
for (i = FileIndex; i < argc; i++) {
pFileName = argv[i];
/* Нужно из pFileName вытащить сабстринг по разделителю *
FileAddress = ... // тут получение адреса
SetCurrentDirectory(FileAddress);
*/
printf("DIR: %s\n", pFileName);
if (!SetCurrentDirectory(pFileName)) {
printf("Ошибка установки директории %s как текущей...", pFileName);
return 1;
}
else {
ok = TraverseDirectory(pFileName, MAX_OPTIONS, Flags) && ok;
SetCurrentDirectory(CurrPath);
}
}
}
return ok ? 0 : 1;
}
static BOOL TraverseDirectory(LPCTSTR PathName, DWORD NumFlags, LPBOOL Flags) {
HANDLE SearchHandle;
WIN32_FIND_DATA FindData;
BOOL Recursive = Flags[0];
DWORD FType, iPass;
TCHAR CurrPath[buffsize + 1];
GetCurrentDirectory(buffsize, CurrPath);
for (iPass = 1; iPass <= 2; iPass++) {
SearchHandle = FindFirstFile(PathName, &FindData);
if (SearchHandle == INVALID_HANDLE_VALUE) {
pr_err(GetLastError());
return 1;
}
do {
FType = FileType(&FindData);
if (iPass == 1)
ProcessItem(&FindData, MAX_OPTIONS, Flags);
if (FType == TYPE_DIR && iPass == 2 && Recursive) {
_tprintf(_T("%s\\%s:\n"), CurrPath, FindData.cFileName);
if (!SetCurrentDirectory(FindData.cFileName))
{
printf("Ошибка установки %s как текущей директории...", FindData.cFileName);
}
else {
TraverseDirectory(_T("*"), NumFlags, Flags);
SetCurrentDirectory(_T(".."));
}
}
} while (FindNextFile(SearchHandle, &FindData));
FindClose(SearchHandle);
}
return TRUE;
}
static BOOL ProcessItem(LPWIN32_FIND_DATA pFileData, DWORD NumFlags, LPBOOL Flags)
{
const TCHAR FileTypeChar[] = { 'c', 'd' };
DWORD FType = FileType(pFileData);
BOOL Long = Flags[1];
SYSTEMTIME LastWrite;
if (FType != TYPE_FILE && FType != TYPE_DIR)
return FALSE;
_tprintf(_T("\n"));
if (Long) {
_tprintf(_T("%c"), FileTypeChar[FType - 1]);
_tprintf(_T("%10d"), pFileData->nFileSizeLow);
FileTimeToSystemTime(&(pFileData->ftLastWriteTime), &LastWrite);
_tprintf(_T(" %02d/%02d/%04d %02d:%02d:%02d "), LastWrite.wMonth, LastWrite.wDay,
LastWrite.wYear, LastWrite.wHour, LastWrite.wMinute, LastWrite.wSecond);
}
_tprintf(_T("%s"), pFileData->cFileName);
PrintAttributes(GetFileAttributesA(pFileData->cFileName));
return TRUE;
}
static DWORD FileType(LPWIN32_FIND_DATA pFileData) {
BOOL IsDir;
DWORD FType;
FType = TYPE_FILE;
IsDir = (pFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
if (IsDir)
if (lstrcmp(pFileData->cFileName, _T(".")) == 0 ||
lstrcmp(pFileData->cFileName, _T("..")) == 0)
FType = TYPE_DOT;
else
FType = TYPE_DIR;
return FType;
}
问题是切换到指定路径不起作用。我该如何解决这个问题?
【问题讨论】:
-
我们不知道代码的作用。它使用通用文本映射,由我们看不到的外部环境控制。无论如何,我们需要minimal reproducible example。