2

私は、64 ビット Windows 7 マシンで Visual C++ 2010 Express を使用して単純な Windows プログラムに取り組んできました。これまでのところ、編集可能なテキスト領域を備えたシンプルなメニューがあります。ユーザーがメディア ファイル (映画または音楽ファイル) を選択し、既定のプログラムを使用して再生できるようにしようとしています。

ユーザーがメニューから File->Play->File from Computer を選択すると、次のコードが実行されます。

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

問題は、最初のシステム コールが期待どおりに実行されることです。2 番目の呼び出しでは、「cmd.exe は、内部または外部コマンド、操作可能なプログラム、またはバッチ ファイルとして認識されていません」と通知されます。File Open 関数内に 2 番目のシステム コールを配置しようとしましたが、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;
            }

        }
    }
4

2 に答える 2

4

関数は、そのGetOpenFileName()操作の一部として作業ディレクトリとドライブを変更します。への呼び出しcdは作業ドライブを変更せず、cmd.exeまだ作業ディレクトリにありません。

解決策は、最終的に何をしようとしているのかによって異なりますが、cmd.exe(環境変数を参照%COMSPEC%) へのフル パスを指定し、コマンド インタープリターに依存しないか、OFN_NOCHANGEDIRフラグを渡して作業を壊さないように指示することができます。ディレクトリ。

(GUI) アプリが特定の作業パスを必要とする本当の理由はないことに注意してください。できることはすべて完全に修飾する必要があります。

于 2011-12-19T00:35:32.767 に答える
0

呼び出し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;  
        }  
    }  
}  
于 2011-12-20T20:25:49.947 に答える