GetOpenFileName и системные ошибки вызова времени выполнения ошибки C ++ Win32 API - PullRequest
2 голосов
/ 19 декабря 2011

Я работал над простой программой для 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 ]

4 голосов
/ 19 декабря 2011

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

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

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

0 голосов
/ 21 декабря 2011

Вызов 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;  
        }  
    }  
}  
...