Visual Basic 6.0でWin32APIを用いてRS-232Cで通信するプログラムのハンドル番号の取得方法

このQ&Aのポイント
  • Visual Basic 6.0でWin32APIを用いてRS-232Cで通信するプログラムのハンドル番号を知る方法について紹介します。
  • シリアルポートを開いた状態でプログラムを終了してしまった場合、ポートが開いたままとなり、再度プログラムを実行することができません。
  • しかし、プログラム上で現在シリアルポートを開いているハンドル番号を知る方法があります。この方法を利用することで、手動でハンドル番号をメモする必要がなくなります。
回答を見る
  • ベストアンサー

Visual Basic 6.0でWin32APIを用いてRS-232

Visual Basic 6.0でWin32APIを用いてRS-232Cで通信するプログラムを作っています。 CreateFile()でポートを開き、ハンドル番号を得て、プログラム終了前にそのハンドルを指定してCloseHandle()シリアルポートをクローズします。 ところが、何らかの原因でそのハンドルのクローズを行わなかった場合(例えば、デバッグ中にプログラムを終了させる)、シリアルポートは開っぱなしのようで、再度プログラムを実行しようとするとCreateFile()でポートを開くことが出来ません。 この状態は、VB6を再起動しない限り続きます。 そこでお聞きしたいのですが、プログラム上で、現在シリアルポートを開いているハンドル番号を知る方法はあるのでしょうか? 開いたときにメモするのも煩わしいため、なんとかならないかと悩んでいます。 どうぞよろしくお願いします。

noname#230227
noname#230227

質問者が選んだベストアンサー

  • ベストアンサー
  • reset_cat
  • ベストアンサー率68% (94/138)
回答No.4

VB6.0でデバック実行している場合、VCやVB.netなどど違い、VB6.0のIDEプロセスの内部で実行されます。そのため、質問のようにハンドルクローズを忘れたりすると、IDEがそのハンドル保持プロセスとなるため、ハンドルを無理やり指定してもう一度IDEで閉じさせるか、IDEそのものを落とすしか方法がなくなります。(正直ほとんどバグぢゃないのか?って気がしますが・・・) 対策方法は#2さんや#3さんが回答されている方法が現実的だと思います。 余談ですが・・・今VB6.0で作るのは正直オススメできないですね・・・Windows7ではデバックできないし・・・

その他の回答 (3)

  • BellBell
  • ベストアンサー率54% (327/598)
回答No.3

サブクラス化してやると安全にシリアルポートが閉じることはできそうですが。 ※ただ本来の使用方法から考えると邪道な方法 過去には、サブクラス化する事でデバッグ時に正しく終了しないと、VBごと落ちるという問題がありました。 その問題へのプログラミング手法として対策が考えられて、 WM_NCDESTROY メッセージは、VB-IDEから終了された場合でもデバッグ中のプログラムで受け取れる事が判った。 つまり、元々サブクラス化しているのでWM_NCDESTROYメッセージが受け取れる。 そのメッセージでサブクラス化を終了させれば、VB-IDEから終了された場合でも問題がないと。 応用すれば、VB-IDEから終了されてポートが開きっぱなしってのは防げます。 ま、もしかしたらステップ実行した場合、Endで終了した場合にVBごと落ちるような事は発生するかも知れません。 ※私自身は経験がないですが。 開発上の都合の為だけにサブクラス化、邪道かも知れませんが場合によっては便利です。

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.2

No1 の回答と同意ですが、 Open 時に Debug.Print で出力しておけばいいだけではないでしょうか

  • koi1234
  • ベストアンサー率53% (1866/3459)
回答No.1

何をしたいのか良くわかりませんが 強制的にハンドル番号だけを合わせてクローズ関数だけ 呼んでもしても多分閉じないんじゃないかと思いますが (あくまで予想やったことなし) ためしでやるのであればオープンで取得したハンドル番号を どこかのファイルに書き出す(簡単なのはINIファイル) 等すれば可能でしょう

noname#230227
質問者

補足

回答ありがとうございます。 > 強制的にハンドル番号だけを合わせてクローズ関数だけ > 呼んでもしても多分閉じないんじゃないかと思いますが ハンドル番号をメモしておいて、後からCloseHandle()を呼び出せば、ポートは閉じるのは確認しました。 MSCommを使ってプログラムを開発していたときは、VBのIDEに制御が戻ればポートは勝手に閉じていたのですが、Win32APIを使うと、ポートを閉じずにIDEに制御が戻ったとき、ポートが開っぱなしになり、VisualBasicを一旦終了しない限りそれが続くんです。 もしかして、コンパイルして実行形式になったプログラムでは発生しない問題なのかもしれません。 普通、あるプログラムが開いたハンドルは、そのプログラムで閉じずに終了してもOSが閉じますよね?

関連するQ&A

  • Win32APIのWriteFile()でRS-232Cポートにデータ

    Win32APIのWriteFile()でRS-232Cポートにデータを送信出来ません。 WriteFile()実行後、GetLastError()でエラーコードを確認したところ、6を返していました。 このエラーは、 6 ERROR_INVALID_HANDLE 6 0x00000006 ハンドルが無効です なので、指定したハンドル番号が無効だからエラーが出るようなのですが、実際にはCreateFile()が返したハンドル番号を指定していますので、なぜこのエラーが出るのか分かりません。 環境は、VMWare 5.5 + Windows 2000 + Visual Basic 6.0 です。 なにかヒントになることがありましたら、どうぞよろしくお願いします。

  • CloseHandle以外でファイルを閉じる方法

    CreateFileでファイルをオープンした後、うっかりCloseHandleせずにプログラムを終了してしまったとします。 するとそのファイルは、Windowsを再起動するまで、削除できなくなりますよね。 これを、再起動せずにクローズする方法ってないもんでしょうか? もう一度プログラムを実行しても、ハンドルオープンしたままですから、当然CreateFileも失敗しますし……。 よくファイル操作するプログラムを作るのですが、しょっちゅうCloseHandleし忘れて再起動するハメになるので、再起動なしでクローズできる方法があれば非常にありがたいのです。 やっぱり、素直に再起動するしかないんでしょうか。

  • VB2005でWin32APIを用いてRS-232CのRTS信号を、デ

    VB2005でWin32APIを用いてRS-232CのRTS信号を、データ送信中だけHIGHにさせるプログラムを作成中です。 色々調べて、Win32APIを使うことで、それらしい動作をさせるプログラムを作れることが分かり、色々調べてコーディングしたのですが、上手く動きません…。処理の流れは以下のようになっています。 (1) CreateFile()関数でCOMを開く。   (CreateFile()の「フラグ」には"FILE_FLAG_OVERLAPPED"を指定) (2) CreateEvent()関数にてイベントオブジェクトを作成。 (3) EscapeCommFunction()でRTS信号をHIGHに設定。 (4) WriteFile()関数でRS-232Cへデータを送信する。 ※ここまでは、オシロスコープにて正しく動作していることを確認しています。 (5) データ送信完了を待つために、SetCommEvent()関数で"EV_TXEMPTY"イベントマスクをセット。 (6) WaitCommEvent()で送信完了を待つ。   ⇒WaitCommEvent()関数が、データ送信完了を待たずに抜けてきてしまう(Falseがリターンされる)…。 (7) そこで、WaitForSingleObject()を使ってイベントハンドラが"シグナル状態"になるのを待つ。   ⇒タイムアウトに"INFINITE"を指定すると、無限待ち状態に陥ってしまう。   ⇒また、タイムアウトに"1000"を指定すると、約1秒後に"WAIT_TIMEOUT"が返ってきてしまう。 WriteFile()関数、そしてWaitCommEvent()関数の引数には、OVERLAPPED構造体へのポインタを渡しているのですが、思うように動いてくれません。 ※Win32APIの関数宣言の記述方法(データ型など)が誤って、このようになっていたりするのでしょうか… どなたかヒントでもお教えいただけると、大変助かります。 以上、よろしくお願いいたします。

  • Win32APIでシリアル通信をするには?

    Win32APIとVB.NETを使ってシリアル通信をするプログラミングを考えています。概要はGPS端末からのデータをVBで受信して表示できるようなプログラムを目指していますが、APIの使い方が分からないので詳しく教えていただける方がいましたら、サンプルソースまたは参考Webサイトの教示をお願いします。 VB6.0のクラス(MSComm)を追加する方法ではなく、APIを使う方向で回答お願いします。

  • WIN32API CreateFileのCOMx

    WIN32API CreateFile(…"COMx"…)のCOM番号「x」)は、1~256まで可能ですか。 MS-VC++でRS-232C通信のWIN32アプリケーションを作る必要が生じてきました。 VC++6.0やVS2005のシステムは所有していますが、WIN32アプリは初心者です。 (WIN32アプリが出来たらDLLに改造するつもりです。) http://www.saluteweb.net/~oss_winapi232.html ここにどなたかが、サンプルプログラムをアップされてます。 この中の("COM1")は、"COM1"~"COM256"まで、対応しているんでしょうか。

  • VB2010でのAPIの使い方を教えてください。

    お世話になります。VB初心者です。ごくごく基本的なことを教えてください。 VB2010にて、PCとUSBを介して繋がっている機器からデータのやり取りを行おうとしています。 そのためのAPIが、機器メーカから***.dllという形で提供されています。同様に、これを使ったサンプルソフトもついているのですが、VB6で作ったものなので、VB2010ではそのまま使えません。 このAPIには、USBポートのOpen/CloseやRead/Writeなどの関数があるので、これを使いたいのですが、具体的にプログラム上で、どういうふうに定義(?)すればいいのでしょうか? APIの仕様書には、「API 使用時には ***.h をインクルードして使用してください→#include “***.h”」、「リンク時には、***.lib もリンクしてください」などと書かれています。 まだ、VB2010を勉強し始めたばかりなので、こういう基本的な部分がわかっていません。 お教えいただけると助かります。よろしくお願いします。

  • VB.netでRS232Cポートを使うには

    Visual Basic.net でRS232C PORTを使いたいのですが、具体的な方法を教えてください。(WIN32 APIを経由して駆動するようなのですが。)

  • COMポートが存在するかどうかを調べるには?

    Windows APIでプログラムしています。 とあるCOMポートが存在するかどうかをチェックしたいと思っています。今まではCreateFile関数でポートを開いてみて、INVALID_HANDLEを返したらポートは存在しないというロジックを使っていたのですが、すでにポートが開いている状態でCreateFileを再び使うとINVALID_HANDLEを返してしまうので、ポートは存在するのに「存在しない」という判定になってしまうトラブルが起きました。 他の方法でポートの存在を確認する方法はありますか?

  • Visual Basicのエラーについて

    「Visual Basicでエンジョイプログラミング」(CQ出版社) いう本に掲載されている「シリアルポートの機能調査」 というプログラムを書いたのですが実行したら 下に書いてあるプログラムのdummy = GetCommProperties(hComm, prop) の部分の「prop」の文字色が変わって 「コンパイルエラー ByRef 引数の型が一致しません。」 と表示されたのですがどこをどう直せばいいかよくわかりません。 何かわかる方がいましたら教えてください。 よろしくお願いします。 'フォームモジュール Form1 Private Sub Form_Load() Command1.Caption = "制御信号線の調査" End Sub Private Sub Command1_Click() 'シリアルポートをオープンする Const GENERIC_READ = &H80000000 Const GENERIC_WRITE = &H40000000 Const OPEN_EXISTING = 3 dummy = CloseHandle(43) comname = "COM1" hComm = CreateFile(comname, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0) If hComm = -1 Then MsgBox comname & "が使えません", 16 End End If Print "ハンドル番号"; hComm dummy = GetCommProperties(hComm, prop) flg = prop.dwProvCapabilities Const PCF_DTRDSR = &H1& Const PCF_RTSCTS = &H2& If flg And PCF_DTRDSR Then Print "DTR/DSRが使用できます" If flg And PCF_RTSCTS Then Print "RTS/CTSが使用できます" dummy = CloseHandle(hComm) End Sub

  • シリアル通信について。

    PICからPCにデータ(電圧:最大値5)を受信させようとしています。 受信には C++を用いたプログラムを自作したいのですが、 どうしてもうまくいかなかったため投稿させていただきました。 症状としては、まずポートを開く事すら出来ていません。 RS232c {USBで変換) が接続されているポートはCOM1です。 ポートが開くか確かめるプログラムとしては、次のようなソースを使いました。 #include<windows.h> #include<iostream> using namespace std; int main(void){ HANDLE hCom; hCom = CreateFile( (LPCWSTR)"COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if (hCom == INVALID_HANDLE_VALUE) { cout<<"シリアルポートを開くことが出来ませんでした。\n"<<endl; return false; } CloseHandle( hCom ); return 0; } これを実行すると「シリアルポートを開くことが出来ませんでした。」としかなりません。 ( (LPCWSTR)"COM1"となっているのは、「'CreateFileW' : 1 番目の引数を 'const char [5]' から 'LPCWSTR' に変換できません。」  と出てしまったためです。) ハイパーターミナルを用いてCOM1からデータを受信できていることは確認しましたので、 通信が出来ていないわけではないようなのです。 ありふれた質問である事は重々承知の上ですが、 このソースでシリアルポートが開けない理由を教えていただければ幸いです。 環境:Visual C++ 2008 Express Edition Microsoft Windows XP Version 2002 Service Pack 3