web-dev-qa-db-ja.com

ハンドルが有効かどうかを確認する方法は?

C++では、HANDLEのあるシリアルポートを開きました。外部アプリケーションによってポートが閉じる可能性があるため、データを読み取る前にHANDLEがまだ有効であることをどのように確認できますか?

HANDLEを適切なAPI関数と照合することで実行できると思いますが、どれですか。ありがとうございました。

19
losingsleeep

ハンドルが「有効」であるかどうかを確認することは間違いです。これに対処するより良い方法が必要です。

問題は、いったんハンドルが閉じられると、別の何かを新しく開くことで同じハンドル値が生成される可能性があり、テストではハンドルが有効であると表示されるかもしれませんが、自分が思っているファイルを操作していないということです。

たとえば、次のシーケンスを考えてみます。

  1. ハンドルが開いています。実際の値は0x1234です
  2. ハンドルが使用され、値が渡されます
  3. ハンドルが閉じています。
  4. プログラムの他の一部がファイルを開き、ハンドル値0x1234を取得します
  5. 元のハンドル値は「有効性がチェックされ」、合格します。
  6. ハンドルが使用されており、間違ったファイルを操作しています。

したがって、それがプロセスである場合、有効なハンドルと無効なハンドルを追跡する必要があります。他のプロセスからハンドルを取得した場合は、DuplicateHandle()を使用してプロセスに配置されています。その場合、ハンドルの有効期間を管理する必要があり、ソースプロセスはそれを行うべきではありません。あなたのハンドルが別のプロセスから閉じられている場合、私はあなたがそうしているのだと思います、そしてあなたは簿記に対処する必要があります。

18
janm

一部のWinAPI関数は、有効なハンドルが渡されても意味のないERROR_INVALID_PARAMETERを返すため、ハンドルの有効性をチェックする実際のユースケースはあります

GetHandleInformation関数がその仕事をします: http://msdn.Microsoft.com/en-us/library/ms724329%28v=vs.85%29.aspx

7
Krit

外部アプリケーションによってポートが閉じる可能性があるため

これは不可能です。外部アプリケーションは、CloseHandle()に渡す適切なハンドル値を取得できません。ポートを開いたら、ポートへのハンドルを取得しようとする他のプロセスはAccessDeniedを取得します。

とはいえ、プロセスのハンドルを格納する文書化されていないカーネル構造の秘密の知識を持つことによって、この制限をハックするクラップウェアが世の中に存在しています。あなたは彼らに対して無力です、同じことをすることによってこの戦いに挑むことの間違いをしないでください。負けます。顧客がこれについて不満を言ったら、私の医者に「それが痛いならそれをしないでください」と忠告します。

5
Hans Passant

HANDLEが指定されていて、それが本当に開いているファイルハンドルであるかどうかを確認するだけの場合は、そのためのWindows API関数 GetFileInformationByHandle があります。

ハンドルがファイルに対して許可するアクセス許可に応じて、 SetFilePointer を使用してファイルポインターを移動したり、- ReadFile を使用してデータを読み取ったり、nullを実行したりすることもできます。 WriteFile を使用した書き込み操作、nNumberOfBytesToWriteを0に設定。

1
Felix Dombek

おそらくあなたはウィンドウの下にいて、ReadFileを使用してデータを読み取っています。それをチェックする唯一の方法は、読むことです。 HANDLEが無効である場合、おそらくERROR_HANDLE_INVALID

1
RedX

IsWindow() 関数を使用してみてください;-)

IsWindow() は、Windows 2000以降のWindows APIの関数です。

0
Codr

Konuyla ilgiliörnek `

// File handle: CreateFile(), GetHandleInformation() and CloseHandle()
#include <windows.h>
#include <stdio.h>

int main(void)
{
// handle to a file
HANDLE hFile;
// file and path, change accordingly. LPCWSTR is a pointer to a constant
// null-terminated string of 16-bit Unicode characters. It is a typedef:
// typedef CONST WCHAR *LPCWSTR. The modifier 'L' is for wide character.
LPCWSTR fname = L"c:\\testfile.txt";
DWORD lpdwFlags[100];
BOOL test;

// Create a file with the given information...
hFile = CreateFile(fname, // file to be opened
GENERIC_WRITE, // open for writing
FILE_SHARE_WRITE, // share for writing
NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL |FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
// normal file archive and impersonate client
NULL); // no attr. template

if(hFile == INVALID_HANDLE_VALUE)
printf("Could not open %s file, error %d\n", fname, GetLastError());
else
{
printf("File's HANDLE is OK!\n");
test = GetHandleInformation(hFile, lpdwFlags);
printf("The return value is %d, error %d\n", test, GetLastError());
}
// when finished, close the file handle
CloseHandle(hFile);
DeleteFile(fname);
return 0;
}`

作成者 http://www.tenouk.com/cpluscodesnippet/createfilegetclosehandleinfo.html

0
İbrahim Doğan

私は少し遅れていることを知っていますが、パイプ(CreateFileを使用して作成したパイプ)がまだ開いているかどうかを確認する方法(おそらくもう一方の端が接続をシャットダウンしている)を確認して、それは、それを再び開くことではありません。 @Felix Dombekが提案したことを行い、WriteFileを使用して接続を確認しました。 1が返された場合は、パイプが開いていることを意味します。それ以外の場合は、CreateFileを使用して再度開きました。これは、パイプが二重であることを意味します。 CreateFileは次のとおりです。
hPipe2 = CreateFile(lpszPipename2, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL);
これが接続を確認する方法です:

while(1)
{   
    bool MessageSent = WriteFile(hPipe2, "Test", 0, &cbWritten, NULL);
    if (!(MessageSent))
    {
        LogsOut("Read pipe has been disconnected");
        //Call method to start the pipe again
        break;
    }
    Sleep(200); // I need this because it is a thread
}

これは私にとってはうまくいきます:)

0
CompuPlanet