GetOpenFileNameとシステム関数呼び出しのランタイムエラーc ++ win32 api

私は64ビットWindows 7マシンでVisual C ++ 2010 expressを使用して簡単なWindowsプログラムに取り組んできました。これまで私は簡単なメニューと編集可能なテキストエリアを持っていました。私はユーザーがメディアファイル(ムービーまたは音楽ファイル)を選択し、デフォルトのプログラムを使用してそれを再生できるようにしようとしています。

When the user selects from the menu File->Play->File from Computer it runs the following code.

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

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

        }
    }
2
システムコールとは何ですか?私はその必要性を理解していません。フラグに OFN_NOCHANGEDIR を含めてみてください。デフォルトプレーヤーでファイルを再生する場合は、 ShellExecute を使用します。
追加された 著者 David Heffernan,

2 答え

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

解決策は、最後に何をしようとしているかによって異なりますが、 cmd.exe %COMSPEC%環境変数を参照)コマンド・インタプリタに頼ったり、 OFN_NOCHANGEDIR フラグを渡して作業ディレクトリを壊さないようにしてください。

(GUI)アプリケーションが特定の現用パスを要求する本当の理由はないことに注意してください。できる限りすべての資格を取得する必要があります。

4
追加された

cd コマンドが有効であっても(そうでない場合でも)、作業ディレクトリを変更するので問題はありません( system()を呼び出すと新しいプロセスが開始されます)あなたのアプリのプロセスではなく、別のプロセスのアプリケーションのプロセスの作業ディレクトリを設定するには、 system()の代わりに SetCurrentDirectory()を使用します。

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

しかし、 GetOpenFileName() OFN_NOCHANGEDIR フラグが自動的に内部的に処理されるため、手動で行う必要はありません。呼び出し元プロセスの作業ディレクトリが何であれ、 OFN_NOCHANGEDIR が指定されている場合、 GetOpenFileName()はそのコードを保持します。

これを試して:

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;  
        }  
    }  
}  
0
追加された