GetOpenFileName и системные ошибки вызова времени выполнения ошибки C++ Win32 API

Я работал над простой программой для Windows, использующей Visual C++ 2010 Express, на 64-битной машине с Windows 7. Пока у меня есть простое меню с редактируемой текстовой областью. Я пытаюсь позволить пользователю выбрать медиафайл (фильм или музыкальный файл) и воспроизвести его с помощью программы по умолчанию.

Когда пользователь выбирает из меню Файл-> Воспроизвести-> Файл с компьютера, он запускает следующий код.

    case ID_PLAY_FFC:
    {
        system("cd c:/windows/system32/&&cmd.exe");
        FileOpen(hWnd);
        system("cd c:/windows/system32/&&cmd.exe");
    }
    break;

Проблема в том, что первый системный вызов выполняется, как и ожидалось. Второй вызов говорит мне, что "cmd.exe не распознается как внутренняя или внешняя команда, работающая программа или пакетный файл". Я попытался поместить второй системный вызов в функцию открытия файла, и он, кажется, работает в любом месте до GetOpenFileName, но не после.

Единственное, что мне действительно нужно, - это путь к файлу, поэтому мне было интересно, знает ли кто-нибудь, как решить эту проблему или лучший способ сделать это?

код для FileOpen():

    void FileOpen(HWND hwnd)
    {
        OPENFILENAME ofn;           // common dialog box structure
        char szFile[MAX_PATH];      // buffer for file name MAX_PATH = 260
        HANDLE hf;                  // file handle

        // Initialize OPENFILENAME
        ZeroMemory(&ofn, sizeof(ofn));
        ofn.lStructSize = sizeof(ofn);
        ofn.hwndOwner = hwnd;
        ofn.lpstrFile = szFile;

        // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
        // use the contents of szFile to initialize itself.
        ofn.lpstrFile[0] = '\0';
        ofn.nMaxFile = sizeof(szFile);
        ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0";
        ofn.nFilterIndex = 1;
        ofn.lpstrFileTitle = NULL;
        ofn.nMaxFileTitle = 0;
        ofn.lpstrInitialDir = NULL;
        ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

        // Display the Open dialog box.
        //system("cd c:/windows/system32/&&cmd.exe"); will execute here.

        if (GetOpenFileName(&ofn)==TRUE)
        {
            //system("cd c:/windows/system32/&&cmd.exe"); but not here.
            hf = CreateFile(ofn.lpstrFile,
                    GENERIC_READ,
                    0,
                    (LPSECURITY_ATTRIBUTES) NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL,
                    (HANDLE) NULL);
            if (hf == (HANDLE)-1)
            {
                MessageBox(NULL,"Could not open this file", "File I/O Error", MB_ICONSTOP);
                return;
            }

        }
    }

2 ответа

Решение

GetOpenFileName() функция меняет рабочий каталог и диск как часть своей работы. Ваш звонок в cd не меняет рабочий диск и cmd.exe все еще не в рабочем каталоге.

Решение зависит от того, что именно вы пытаетесь сделать в конце концов, но вы можете указать полный путь к cmd.exe (См. %COMSPEC% переменной среды) и не полагаться на интерпретатор команд, или передать OFN_NOCHANGEDIR флаг, чтобы сказать, чтобы он не загромождал рабочий каталог.

Обратите внимание, что для приложения (GUI) нет реальной причины требовать определенного рабочего пути. Вы должны полностью квалифицировать все, что можете.

Призвание system() начинает новый процесс, так что даже если ваш cd Команды были действительны (что они не являются), это не имеет значения, потому что вы изменили бы рабочий каталог другого процесса, а не процесс вашего приложения. Чтобы установить рабочий каталог процесса вашего приложения, используйте SetCurrentDirectory() вместо system()Например:

case ID_PLAY_FFC:     
{     
    SetCurrentDirectory(TEXT("c:/windows/system32/"));     
    FileOpen(hWnd);     
    SetCurrentDirectory(TEXT("c:/windows/system32/"));     
}     
break;

Однако вам не нужно делать это вручную, потому что OFN_NOCHANGEDIR флаг GetOpenFileName() автоматически обрабатывает это для вас. Каким бы ни был рабочий каталог вызывающего процесса, GetOpenFileName() сохранит это когда OFN_NOCHANGEDIR указан.

Попробуй это:

case ID_PLAY_FFC: 
{
    FileOpen(hWnd); 
}
break; 


void FileOpen(HWND hwnd)
{
    OPENFILENAME ofn;           // common dialog box structure
    TCHAR szFile[MAX_PATH+1];   // buffer for file name MAX_PATH = 260

    // Zero out szFile so that GetOpenFileName does
    // not use the contents to initialize itself.
    ZeroMemory(szFile, sizeof(szFile));

    // Initialize OPENFILENAME
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hwnd;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFilter = TEXT("All\0*.*\0Text\0*.TXT\0");
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;

    // Display the Open dialog box.
    if (GetOpenFileName(&ofn)==TRUE)  
    {  
        int ret = (int) ShellExecute(
                          hwnd,
                          NULL,
                          ofn.lpstrFile,
                          NULL,
                          TEXT("c:/windows/system32/"),
                          SW_SHOWNORMAL);
        if (ret <= 32)
        {  
            MessageBox(NULL, TEXT("Could not open this file"), TEXT("File I/O Error"), MB_ICONSTOP);  
            return;  
        }  
    }  
}  
Другие вопросы по тегам