Winsockを使わずにVBでSocketを利用したいと考えています.事情がありましてコンポーネントを使わずにSocket通信でサーバープログラムと通信を行いたいです.
APIなどでSocket関係の関数は用意されているのでしょうか?
宜しくお願いします.


OS:Windows2000+SP4
Visual Basic 6.0+SP5

A 回答 (2件)

ソケットで検索↓



参考URL:http://www.vbvbvb.com/jp/gtips/index.html
    • good
    • 0
この回答へのお礼

回答ありがとうございます.
たくさんの例がのっており大変助かりました.
今から1つずつ調べたいと思います。

お礼日時:2003/09/11 15:40

私もwsock32.dllのAPI関数だけ作ったことがあるけど、結構大変だったです。



私の場合は、下記を参考にして作りました。

参考URL:http://hp.vector.co.jp/authors/VA022513/program. …
    • good
    • 0
この回答へのお礼

回答ありがとうございます.
紹介して頂いたサイトのソースコードの解析を早速行います.

お礼日時:2003/09/11 15:39

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QEXCEL2000でVBAでWinsockをしたい

こんにちは。
EXCEL2000を使用してEXCEL VBAにてWinsockを使用したいです。
Visual Basic6.0をインストールしているのですが、
EXCEL VB Editorにて「参照設定」の欄に
Microsoft Winsockがありません。
どうしたら、追加できるのでしょうか?
Visual Basic6.0にはWinsockは搭載していると思うのですが、

Aベストアンサー

はて。。これかな
http://shoji.blog1.fc2.com/blog-entry-80.html

参照設定→参照→system32下のMSWINSCK.OCXを参照する。
それかAPIを使ってwsock32.dllを参照する。

QExcelVBAでのwinsockの利用

だいぶ以前に、VB6を使ってマニュアル片手にtcpやudpによるLAN内での双方向データ転送(チャットごっこ)ができるものを作った経験があります。
最近、Excel2010のVBAを使って当時のようなものを作ってみたいと考え、CQ出版の「VBAによるTCP/IPプログラミング入門」を購入しました。読んだ限りではなんとかなりそうに思ったのですが、その中で、「Winsockコントロールはプログラム開発し配布するためにはそのライセンスが必要でライセンスなしではWinsockコントロールを配置してダイアログを作成できない」という記述がありました。つまりはVB6などのライセンスがある環境でないと作り始めることができないようです。
幸いVB6はうちの古いパソコンに入っていますから、そちらに入っているExcelでWinsockコントロールを配置しただけのVBAファイルを作り、今のExcel2010に持って来て修正していくのであれば作業は可能らしいのですが、いずれは破棄するであろうパソコンに依存しないといけないという流れがしっくり来ません。
また、VB6を今の環境に移せば解決する話だとも思いますが、今後VBAは使ってもVB6を使うことはないだろうということと、容量等の事情から、できればこちらに入れるようなことはしたくありません。

必要に迫られてもいなく少々わがままな事情も合わせての話ですが、何か解決方法がありましたら提案・指摘などをお願いいたします。

だいぶ以前に、VB6を使ってマニュアル片手にtcpやudpによるLAN内での双方向データ転送(チャットごっこ)ができるものを作った経験があります。
最近、Excel2010のVBAを使って当時のようなものを作ってみたいと考え、CQ出版の「VBAによるTCP/IPプログラミング入門」を購入しました。読んだ限りではなんとかなりそうに思ったのですが、その中で、「Winsockコントロールはプログラム開発し配布するためにはそのライセンスが必要でライセンスなしではWinsockコントロー...続きを読む

Aベストアンサー

直接WinSockのDLLを使えば問題ありません。
DLLの関数は必ずクラスモジュール上で定義し、
インスタンス化してから使います。
'定数
Private Const AF_INET     As Long = 2
Private Const SOCK_STREAM As Long = 1
Private Const IPPROTO_TCP As Long = 6
Private Const INVALID_SOCKET As Long = -1
Private Type sockaddr_in
アドレスファミリ As Integer
ポート番号 As Integer
IPアドレス As Long
予備(7) As Byte
End Type
'初期化
Private Declare Function WSAStartup Lib "WS2_32" _
  (ByVal バージョン As Integer,データ As Byte) As Long
'クリア
Private Declare Function WSACleanup Lib "WS2_32" _
  () As Long
'ソケット作成
Private Declare Function socket Lib "WS2_32" _
  (ByVal アドレスファミリ As Long, ByVal ソケット形式 As Long, _
  ByVal プロトコル As Long) As Long
'アドレス変換
Private Declare Function inet_addr Lib "WS2_32" _
  (ByVal IPアドレス As String) As Long, _
'接続
Private Declare Function connect "WS2_32" _
  (ByVal ソケット As Long, アドレス As sockaddr_in, _
  ByVal アドレス長 As Long) As Long, _
'送信(文字列)
Private Declare Function sendA "WS2_32" Alias "send" _
  (ByVal ソケット As Long, ByVal データ As String, _
  ByVal データ長長 As Long, ByVal フラグ As Long) As Long, _
'送信(バイナリ)
Private Declare Function sendB "WS2_32" Alias "send" _
  (ByVal ソケット As Long, データ As Byte, _
  ByVal データ長長 As Long, ByVal フラグ As Long) As Long, _
'受信(バイナリ)
Private Declare Function recvB "WS2_32" Alias "send" _
  (ByVal ソケット As Long, データ As Byte, _
  ByVal データ長長 As Long, ByVal フラグ As Long) As Long, _
'ソケット閉鎖
Private Declare Function closesocket Lib "WS2_32" _
  (ByVal ソケット As Long) As Long
サンプル
Public Sub サンプル()
Dim 戻り値 As Long
Dim ソケット As Long
Dim アドレス As sockaddr_in

'初期化する
ReDim データ(397) As Byte
戻り値 = WSAStartup(&H202, データ(0))
Erase データ '初期化で返されるデータは不要なので棄てる
If 戻り値 <> 0 Then
  MsgBox "初期化エラー Code=" & Err.LastDllError
  Exit Sub
End If
'必ずクリーンアップを通るよう制御する
Do
  'TCPIPストリーム(HTTPやFTP用)のソケットを作る
  ソケット = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
  If ソケット = INVALID_SOCKET Then
    MsgBox "ソケット作成エラー Code=" & Err.LastDllError
    Exit Do
  End If
  'サーバに接続する
  アドレス.アドレスファミリ = AF_INET
  アドレス.ポート番号 = 23 '★FTPのポート番号
  アドレス.IPアドレス = inet_addr("192.168.0.1")
  戻り値 = connect(ソケット, アドレス, Len(アドレス))
  If 戻り値 <> 0 Then
    MsgBox "接続エラー Code=" & Err.LastDllError
    Exit Do
  End If
  Dim コマンド As String
  Dim 応答 As String
  Dim 文字 As Byte
  Do
    '1バイトずつ受信する
    戻り値 = recvB(ソケット, 文字, 1, 0)
    '戻り値は受信バイト数なので0以下はエラー(切断)である
    If 戻り値 <= 0 Then
      MsgBox "受信エラー Code=" & Err.LastDllError
      Exit Do
    End If
    応答 = 応答 & Chr(文字)
    'FTPでは応答の末尾は改行なので、検出したらループを抜ける
    If 文字 = 10 Then Exit Do
  Loop
  'その後はプロトコルに従い、sendやrecvでデータを送受信する

  'ソケットを閉じる
  closesocket ソケット
Loop Until True
WSACleanup
End Sub

実際のプログラム例はネットに沢山あります。
但し、殆どがC言語用なので、上記のようにVBに
定義して使います。
データ型はint→Long、WORD→Integer、char→StringまたはByte
ByVal/ByRefの使い分けは単に変数を使う所はByVal、*のある
ポインタならByRefです。

少し厄介なのが受信です。recvはブロック型で、指定バイト数を
受信するまで制御が戻りません。非ブロック型にするか、受信の
有無を調べるか、あるウィンドウに受信を通知してもらってから、
受信するようにします。この3個の方法でWindowsライクなのは
3番目ですが、VBAでは難しいので1番目の方法がよいでしょう。

クラスモジュールにする理由は障害発生時にDLL内部データが
破壊され、その後回復しないためです。標準モジュール内に
関数を定義すると、VBA空間にデータが残るため、プログラムから
解放する方法がありません。クラスモジュールで定義した場合は
クラスを解放(Set 変数 = Nothing)すればデータも解放されます。
次に新しいクラスのインスタンスを作ればDLLも新たにロードされ
るので、障害をひきずりません。

直接WinSockのDLLを使えば問題ありません。
DLLの関数は必ずクラスモジュール上で定義し、
インスタンス化してから使います。
'定数
Private Const AF_INET     As Long = 2
Private Const SOCK_STREAM As Long = 1
Private Const IPPROTO_TCP As Long = 6
Private Const INVALID_SOCKET As Long = -1
Private Type sockaddr_in
アドレスファミリ As Integer
ポート番号 As Integer
IPアドレス As Long
予備(7) As Byte
End Type
'初期化
Private Declare Function W...続きを読む

Qexeファイルのセキュリティ。

社内用のメンテナンスプログラムを制作したのですが、同じプログラムで他社の製品にも使えてしまいます。たいした大きさではないので、フロッピーで十分なんですが社外に流失してしまうとこまってしまいます。
IPアドレスで確認すればいいのですが、登録していないようなものはどうしたらよいのでしょうか?
どなたか、教えていただけませんか?

Aベストアンサー

通信認証のサンプルを作成しました。
(正確に言うと、以前に作成したものがあって、それを抜粋しました)

プロジェクトは二つ必要で、サーバーとクライアントに分かれています。
それぞれにプロジェクトを作成して、EXEを作成してください。
基本はサーバーのEXEが立ち上がった状態で、クライアントのEXEを起動してください。
この書き込みの下の方に「共通の標準モジュール」を記してますが、[INIT_PORT][SERVER_NAME]の各定数があります。
こちらは環境に合わせて変更をしてください。
もし、一台のマシンで実験をするのであればSERVER_NAMEをご自分のマシン名に変更をしてください。

プログラムが正常に動くと、サーバー、クライントが交互に通信状況をメッセージボックスで知らせます。
これはあくまでサンプルなのでそのようにしてますが、サーバー側にはメッセージボックスの機能を使用しないでください。メッセージボックスが表示されている間は、他のユーザーとの通信ができなくなってしまいます。
(VBでそれを回避する方法があるのですが、動作が不安定になるために書きません)

このサンプルでは、互いに文字列を送信しています。
実践では、その文字列をパスワード認証に使用してはいかがでしょうか?



必要なもの

Project1.vbp(サーバー用)
フォーム
Winsock1(インデックスなし)
Winsock2(インデックスあり)

Project2.vbp(クライアント用)
フォーム
Winsock1(インデックスなし)

Winsockはメニューバーより
[プロジェクト]
[コンポーネント]
[Microsoft Winsock Control 6.0(かな?)]
を選択したらツールボックスにWinsockコントロールが現れます。
それをサーバー側に二つ、クライアント側に一つ、各フォームに貼り付けます。
サーバー側のWinsock2にはIndexプロパティに'0'ゼロをセットしてください。
その他のWinsockには値を入力しないでください。

あとは下のソースを貼り付けてください。
-----サーバーのフォーム内のソース(ここから)---------
Option Explicit

Private Sub Form_Load()
  Me.Caption = "SERVER"

  'ポートの初期化を行い、受信待ち状態にする
  On Error GoTo PGMERR
  
  With Me.Winsock1
    .LocalPort = INIT_PORT
    .Listen
  End With
  
  Exit Sub
  
PGMERR:
  Call MsgBox("通信ポートに以上が見られました、終了いたします。", vbSystemModal, Me.Caption)
  End
End Sub

'フォームが閉じる前に、Winsockを全て閉じる
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  Dim wkSock As Winsock
  
  With Me
    .Winsock1.Close
    For Each wkSock In .Winsock2
      wkSock.Close
    Next wkSock
  End With
End Sub

'特定のクライアントのソケットを閉じたとき
Private Sub Winsock2_Close(Index As Integer)
  With Me
    .Winsock2(Index).Close
    Unload .Winsock2(Index)
  End With
End Sub

'メッセージデータの受信
Private Sub Winsock2_DataArrival(Index As Integer, ByVal bytesTotal As Long)
  Dim strRecvData As String    '送られてきたデータ
  Dim lngRecvCnt As Long     '送られてきたデータライン数
  Dim valRecvAry As Variant   '送られてきたデータをライン数のに分解し配列にして記憶
  
  Dim wkVal    As Variant   '受信したメッセージ1文を、IDとメッセージに分解して配列で記憶
  Dim wkSType   As SOCKMSG_ID  '分解した1文のID
  Dim wkStr    As String    '分解した1文のメッセージ
  
  Dim i      As Long     'ループカウンタ
  
  Dim wkMsg    As String    '送信するメッセージ
  
  With Me
  
    'メッセージを受け取る
    .Winsock2(Index).GetData strRecvData
    
    '受信メッセージを、メッセージ分の配列にする
    valRecvAry = Split(strRecvData, vbCrLf)
    
    'メッセージ数を取得
    lngRecvCnt = UBound(valRecvAry)
    
    '受信メッセージの分だけ、一文ずつ処理を行う
    For i = 0 To lngRecvCnt - 1
    
      '一文をIDとメッセージに分解
      wkVal = Split(valRecvAry(i), vbNullChar)
      wkSType = wkVal(0)
      wkStr = wkVal(1)
      
      Select Case wkSType
        Case SOCKMSG_ID.ID1
          wkMsg = "山川豊"
          Call MsgBox("ID1で[" & wkStr & "]を受信しました" & vbNewLine & vbNewLine _
            & "ID1で[" & wkMsg & "]を送信します", vbSystemModal, Me.Caption)
          Call SendMsg(.Winsock2(Index), ID1, wkMsg)
          
        Case SOCKMSG_ID.ID2
          wkMsg = "起動してもいいよ"
          Call MsgBox("ID2で[" & wkStr & "]を受信しました" & vbNewLine & vbNewLine _
            & "ID2で[" & wkMsg & "]を送信します", vbSystemModal, Me.Caption)
          Call SendMsg(.Winsock2(Index), ID2, wkMsg)
      
      End Select
    Next i
  End With
PGMEND:
End Sub

'接続要求がきたら、新たなWinsockを用意する
Private Sub Winsock1_ConnectionRequest(ByVal requestID As Long)
  Dim lngNewIndex As Integer
  
  lngNewIndex = 0
  On Error Resume Next
  
  With Me
    '新たな受信装置を1つ追加する
    Do
      Err.Clear
      lngNewIndex = lngNewIndex + 1
      Load .Winsock2(lngNewIndex)
    Loop Until Err.Number = 0&
    On Error GoTo 0
    
    .Winsock2(lngNewIndex).Accept requestID
  End With
End Sub
-----サーバーのフォーム内のソース(ここまで)---------

-----クライアントのフォーム内のソース(ここから)-------
Option Explicit

'フォームロード時に接続を試みる
Private Sub Form_Load()
  Me.Caption = "CLIANT"

  With Me.Winsock1
    .RemoteHost = SERVER_NAME
    .RemotePort = INIT_PORT
    .LocalPort = 0
    .Connect
  End With
End Sub

'サーバーが落ちた
Private Sub Winsock1_Close()
  Call MsgBox("サーバーが落ちたー", vbSystemModal, Me.Caption)
  Unload Me
End Sub

'サーバーと接続できた
Private Sub Winsock1_Connect()
  Dim wkMsg  As String
  
  wkMsg = "岸部四郎"
  
  Call MsgBox("接続できた" & vbNewLine & vbNewLine _
      & "ID1で[" & wkMsg & "]を送信します", vbSystemModal, Me.Caption)
  Call SendMsg(Me.Winsock1, ID1, wkMsg)
End Sub

'サーバーと接続できなかった
Private Sub Winsock1_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
  Call MsgBox("接続できなかった", vbSystemModal, Me.Caption)
  Unload Me
End Sub

'メッセージデータの受信
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
  Dim strRecvData As String    '送られてきたデータ
  Dim lngRecvCnt As Long     '送られてきたデータライン数
  Dim valRecvAry As Variant   '送られてきたデータをライン数のに分解し配列にして記憶
  
  Dim wkVal    As Variant   '受信したメッセージ1文を、IDとメッセージに分解して配列で記憶
  Dim wkSType   As SOCKMSG_ID  '分解した1文のID
  Dim wkStr    As String    '分解した1文のメッセージ
  
  Dim i      As Long     'ループカウンタ
  
  Dim wkMsg    As String    '送信するメッセージ
  
  With Me
  
    'メッセージを受け取る
    .Winsock1.GetData strRecvData
    
    '受信メッセージを、メッセージ分の配列にする
    valRecvAry = Split(strRecvData, vbCrLf)
    
    'メッセージ数を取得
    lngRecvCnt = UBound(valRecvAry)
    
    '受信メッセージの分だけ、一文ずつ処理を行う
    For i = 0 To lngRecvCnt - 1
    
      '一文をIDとメッセージに分解
      wkVal = Split(valRecvAry(i), vbNullChar)
      wkSType = wkVal(0)
      wkStr = wkVal(1)
      
      Select Case wkSType
        Case SOCKMSG_ID.ID1
          wkMsg = "鳥羽一郎"
          Call MsgBox("ID1で[" & wkStr & "]を受信しました" & vbNewLine & vbNewLine _
            & "ID2で[" & wkMsg & "]を送信します", vbSystemModal, Me.Caption)
          Call SendMsg(.Winsock1, ID2, wkMsg)
          
        Case SOCKMSG_ID.ID2
          Call MsgBox("ID2で[" & wkStr & "]を受信しました" & vbNewLine & vbNewLine _
            & "通信を終了します", vbSystemModal, Me.Caption)
          
          '''''ここに通信が正常にできたことを示すフラグを立てておく
          Unload Me
      End Select
    Next i
  End With
PGMEND:
End Sub
-----クライアントのフォーム内のソース(ここまで)-------

サーバー・クライアントのそれぞれに共通の標準モジュールとして、以下のソースを追加してください。
-----共通の標準モジュール(ここから)-------
Option Explicit

Public Enum SOCKMSG_ID
  ID1 = 1
  ID2 = 2
  ID3 = 3
End Enum
Public Const INIT_PORT As Long = 8000 '←このPORTは使用される確立が高いので、適当な値に変更したほうがいいかも?
Public Const SERVER_NAME As String = "PC_MACHINE_NAME" '←サーバー用のEXEのをおくマシン名

Public Sub SendMsg(inSock As Winsock, inSendType As SOCKMSG_ID, inSendMsg As String)
  Dim wkStr  As String
  
  With inSock
    '通信が可能なときに通信する
    If (.State = (sckConnected)) Then
      '通信の書式は
      ' 1.通信を送るときのID(SOCKMSG_IDを自分で作成、オリジナルの番号を振る)
      ' 2.vbNullChar(IDとメッセージとの区切り文字)
      ' 3.メッセージ(任意の文字列)
      ' 4.vbCrLf(文末を示す)
      wkStr = inSendType & vbNullChar & inSendMsg & vbCrLf
      
      'メッセージを送る
      .SendData wkStr
    End If
  End With
End Sub
-----共通の標準モジュール(ここまで)-------

通信認証のサンプルを作成しました。
(正確に言うと、以前に作成したものがあって、それを抜粋しました)

プロジェクトは二つ必要で、サーバーとクライアントに分かれています。
それぞれにプロジェクトを作成して、EXEを作成してください。
基本はサーバーのEXEが立ち上がった状態で、クライアントのEXEを起動してください。
この書き込みの下の方に「共通の標準モジュール」を記してますが、[INIT_PORT][SERVER_NAME]の各定数があります。
こちらは環境に合わせて変更をしてください。
もし、一台のマ...続きを読む

QVBのソケット通信(winsock)のサイト

VBでwinsockコントロールを使ってソケット通信にて、データの送受信をするプログラミングをするのですが、サンプルコードなどが載っているサイト、わかりやすく説明してあるサイトがありましたら教えてください。

Aベストアンサー

ここの履歴にサンプルが載ってます。。。
っていうか載せました。

わかりやすいかどうかは、わかりませんが・・・

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=155606

QPLCとPCの通信

PLC経験者ですが、VBはまったくの初心者です。
"VB上のボタンが押されたらPLCのデータメモリに10を格納する"
というプログラムを作るには、どうすればよいのでしょうか?

PLCはキーエンスKV5000でイーサネットで通信しようと考えています。
VBの参考書にPLCのことは一言も書いてないので、
何か専用の関数、命令語があるのでしょうか?

よろしくお願いします。

Aベストアンサー

>VBの参考書にPLCのことは一言も書いてないので、
>何か専用の関数、命令語があるのでしょうか?
PLCメーカーが、開発言語用にコンポーネント(API)の提供を行っていない限り、専用の関数というものはありません。

プログラムとして「相手が何か」というのは一切関係ないのです。
「相手と通信するためのI/Fとプロトコル」に合わせるということが重要で、実装が必要な部分になります。
まず、質問者さんが行わなければいけないのは、
>"VB上のボタンが押されたらPLCのデータメモリに10を格納する"
から
・GUIの作成

>イーサネットで通信しようと考えています。
から、
・PLCのプロトコルの確認
・VBでのイーサネット通信の実装
を行う必要があります。

QWinsockのオブジェクトエラー

こんにちは。EXCEL2000・VBAで、Winsockの使用を考えています。
以下のソースコードを入力して、実行してもオブジェクトが見つかりませんという、エラーが出力されてしまいます。
また、Winsockをアクティブにしようと、
User FormにWinsockのアイコンを追加しようとしても
「サブジェクトは指定された操作に対して信頼されません」
という注意書きがでてしまって、追加できません。
なぜ、このようになるのか、教えていただけますか?
よろしくお願いします。

Private Sub CommandButton1_Click()
Winsock1.RemoteHost "www.yahoo.co.jp"
Winsock1.RemotePort 80
Winsock1.Connect
End Sub

Private Sub CommandButton2_Click()
Winsock1.SendData = TextBox1.Value
End Sub

Private Sub CommandButton3_Click()
Winsock1.Close
End Sub

こんにちは。EXCEL2000・VBAで、Winsockの使用を考えています。
以下のソースコードを入力して、実行してもオブジェクトが見つかりませんという、エラーが出力されてしまいます。
また、Winsockをアクティブにしようと、
User FormにWinsockのアイコンを追加しようとしても
「サブジェクトは指定された操作に対して信頼されません」
という注意書きがでてしまって、追加できません。
なぜ、このようになるのか、教えていただけますか?
よろしくお願いします。

Private Sub CommandButton1_Click()
Wi...続きを読む

Aベストアンサー

こんにちは。

以下の内容が的外れだった場合はすみません。m(__)m

下記の参考サイトに書かれているように、Windowsの更新プログラムによりActiveX コントロールが
使えなくなってしまうことによる障害かもしれません。

この場合、現状での対策としては更新プログラム(KB960715)をアンインストールする以外ないように
思われます
注)但し、KB960715をアンインストールした場合、セキュリティが脆弱になる恐れがありますので
  ご注意下さい。

■参考サイト
【Vista】WindowsアップデートによりVBAでActiveXコントロールが使えなくなる
http://lunasite.blog79.fc2.com/blog-entry-56.html

答えてねっと - VBAで今まで使っていたMSFlexGridコントロールが使えなくなった
http://www.biz.kotaete-net.net/Default.aspx?pgid=14&qid=401994224

net3: VBA のマクロとかで FlexGrid が動かない時
http://net-3.blogspot.com/2009/03/vba-flexgrid.html

【VBA】MSHFlexGridの利用不可について
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=48226&forum=7&6

■関連情報
Windows XP の ActiveX Killbits に対するセキュリティ更新プログラム (KB960715)
http://www.microsoft.com/downloads/details.aspx?familyid=18521F44-2861-4A3D-9605-3A9155A737A7&displaylang=ja

Windows Vista の ActiveX Killbits に対するセキュリティ更新プログラム (KB960715)
http://www.microsoft.com/downloads/details.aspx?FamilyID=437defa2-2d07-4718-a4e1-87f96dc73d44&DisplayLang=ja

こんにちは。

以下の内容が的外れだった場合はすみません。m(__)m

下記の参考サイトに書かれているように、Windowsの更新プログラムによりActiveX コントロールが
使えなくなってしまうことによる障害かもしれません。

この場合、現状での対策としては更新プログラム(KB960715)をアンインストールする以外ないように
思われます
注)但し、KB960715をアンインストールした場合、セキュリティが脆弱になる恐れがありますので
  ご注意下さい。

■参考サイト
【Vista】WindowsアップデートによりV...続きを読む

Q[WSH|JS|VB] telnetコマンドの標準出力を受け取りたい

こんにちは。

Windows Scripting Host(WSH)でtelnetコマンドのオートパイロット(自動操縦)をしたいと思っています。
そこで、ログインプロンプトなどを待つ際、waitで時間で待つのではなく、「login:」という文字を待ってログインするようにしたいのですが、できるでしょうか?教えてください。

WSHをご存知ない場合は、VBの範囲でお答えいただければと思います。適用できる可能性がありますので。
なお、言語は、JScript,VBScriptどちらでも構いません。

よろしくお願い致します。

Aベストアンサー

telnet コマンドは、実装が二つありますよね。95 にあった、Window アプリケーションのと
NT のコマンドプロンプトで動くやつ。

Window アプリケーションだと、キーを送り込むのは簡単だが、表示を取るのは、まず、不可能ですよね。

コンソールアプリケーションであれば、どうやってコンソールバッファのハンドルを取得するか
が、難しそう。

rsh もどきが作りたいのであれば、socket を扱うプログラムを作る方が、何百倍も簡単です。

# この回答が、期待に添わないであろう、という意味で自信無しにしておきます

QExcelでTelnetを動かしたい

長々と書いて申し訳ありませんが、困っています。
使用環境はWindows 2000です。開発環境というかexcel2000のVBAでコーディングしています。
で問題点が2点ありまして、
(1)EnumWindowsの所で止まるのですが、AddressOf演算子はexcel2000でも使えますよね。
 コンパイルエラー Sub、Function、または Property が必要です というエラーで止まります。
 何か使用方法が間違っていますでしょうか?
(2)テキストボックスを2つ用意してあるので、それを引数としてtelnetでつなぐパソコンを
 選べるようにしたいのですが引数でうまく渡せません(現状はコメントアウトしている部分です)。

Private Sub CommandButton1_Click()

box1 = TextBox1
box2 = TextBox2
'ipnum = "telnet xxx.xxx."box1"."box2

'待ち時間処理用の時刻の変数
newHour = Hour(Now())
newMinute = Minute(Now())
Shell "cmd.exe"
lRet = Shell("C:\WINNT\system32\cmd.exe", vbNormalFocus)
newSecond = Second(Now()) + 5
waitTime = TimeSerial(newHour, newMinute, newSecond)
Application.Wait waitTime

Call EnumWindows(AddressOf Rekkyo, 0)
lRet = FindWindow(vbNullString, "C:\WINDOWS\system32\cmd.exe")
Call SendMessage(lRet, WM_SYSCOMMAND, WM_MAXIMIZE, ByVal 0&)
Call PostMessageStrings("telnet xxx.xxx.xxx.xxx")
'Call PostMessageStrings(ipnum)
Call PostMessageStrings("xxx.bat")
Call PostMessageStrings("exit")
Call PostMessageStrings("exit")

End Sub

Public Function PostMessageStrings(strPost As String)
Dim i As Integer
'1文字ずつ分解して送信
For i = 1 To Len(strPost)
Call PostMessage(lRet, &H102, Asc(Mid(strPost, i, 1)), 0)
Next
'送信後に改行コードを送信
Call PostMessage(lRet, &H102, 13, 0)
End Function

標準モジュールに、こんな感じでAPI関数を記述してあります。
他のAPIも記述してありますが、割愛してあります。
'ウィンドウのハンドルの取得
Declare Function EnumWindows Lib "user32" (ByVal lpEnumFunc As Long, ByVal lParam As Long) As Long

誰か教えてください。よろしくお願いします。

長々と書いて申し訳ありませんが、困っています。
使用環境はWindows 2000です。開発環境というかexcel2000のVBAでコーディングしています。
で問題点が2点ありまして、
(1)EnumWindowsの所で止まるのですが、AddressOf演算子はexcel2000でも使えますよね。
 コンパイルエラー Sub、Function、または Property が必要です というエラーで止まります。
 何か使用方法が間違っていますでしょうか?
(2)テキストボックスを2つ用意してあるので、それを引数としてtelnetでつなぐパソコンを
 選べるように...続きを読む

Aベストアンサー

>デバックモードで値を見ているとlRetに何も入っていないのでここが悪いと思うのですが

FindWindow() の戻り値が、でしょうか?
それとも、PostMessageStrings() の中で、でしょうか?

よく見てみると lRet がどこで宣言されているのかわかりませんね。
Sub CommandButton1_Click() の中で
Dim lRet As Long
と宣言しているのでしょうか?
そうだとすると、PostMessageStrings() の中の lRet は PostMessageStrings() の中で暗黙に宣言されたものとみなされてしまうので、PostMessageStrings() の中 lRet は 0 になってしまいます。
(General) の (Declarations) で
Private lRet As Long
と宣言するか、PostMessageString() にウィンドウハンドルの引数を追加する必要があります。
だいたい、↓こんな感じですね。
(テキストボックスから取得するところはご自分で適当に直してください。)

(General) - (Declarations)
Private Declare Function FindWindowA Lib "user32" (ByVal cnm As String, ByVal cap As String) As Long
Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMillsecounds As Long)
Private Const WM_CHAR = &H102

Private Sub CommandButton1_Click()
Dim lngRet As Long
Dim hWnd As Long

lngRet = Shell("cmd.exe", vbNormalFocus)

Sleep 100

hWnd = FindWindowA(vbNullString, "C:\WINDOWS\system32\cmd.exe")

SendString hWnd, "telnet xxx.xxx.xxx.xxx"

End Sub

Private Sub SendString(ByVal hWnd As Long, ByVal s As String)
Dim i As Integer
Dim c As String

For i = 1 To Len(s)
c = Mid(s, i, 1)
PostMessage hWnd, WM_CHAR, Asc(c), 0
Sleep 10
Next i

PostMessage hWnd, WM_CHAR, Asc(vbCrLf), 0

End Sub

>デバックモードで値を見ているとlRetに何も入っていないのでここが悪いと思うのですが

FindWindow() の戻り値が、でしょうか?
それとも、PostMessageStrings() の中で、でしょうか?

よく見てみると lRet がどこで宣言されているのかわかりませんね。
Sub CommandButton1_Click() の中で
Dim lRet As Long
と宣言しているのでしょうか?
そうだとすると、PostMessageStrings() の中の lRet は PostMessageStrings() の中で暗黙に宣言されたものとみなされてしまうので、PostMessageStrings() の中 lR...続きを読む

Qエクセル VBA でのCOMポート認識

エクセルのVBAを使用してあるアプリを作成しています。そのアプリはシリアルポートを使用してある機器と接続する事で実現できます。
そこで質問ですが、当該PCが認識しているCOMポートをVBAのSELECT BOXに表示したいのですがどうやれば(どのような関数?)を使用して実装COMポートを認識するのでしょうか?
もちろん、USB<--->シリアルケーブルを使用した場合もCOMポートだと認識しなければなりません。
よろしくお願いいたします。

Aベストアンサー

こんにちは。

Windowsのプログラム(VBA含む)から、COMポートを扱う場合は、WindowsAPI を使用すれば可能
だと思います。

COMポートの実装チェックには、WindowsAPI の「CreateFile」関数でCOMポートのオープンを実行
して、その関数の戻り値がエラーかどうかを見れば判断できると思います。
ただし、COMポートが実装されていてもエラーになるケース(既に使用中、使用不可に設定されて
いるなど)がありますので、その場合はエラーコードを取得してその値で「実装/非実装」を判断しな
いといけないと思います。

以下に、VBA から WindowsAPI (COMポート制御関連を含む)を利用するに当たって、参考になり
そうなサイトを上げてみました。宜しければ覗いてみて下さい。

■参考サイト
注)リンク切れの際は御容赦下さい。

1)VBAでWindowsAPIを使用してシリアル通信を行う方法

◎WindowsAPI講座
http://www.serpress.co.jp/winapi/
・このページよりリンクされている下記項目「シリアル通信(1)~(4)」のページでVBAから通信関連の
 APIを使用する方法が書かれています。
 NO.12 シリアル通信(1) ←必要なWindowAPI定義の説明
 NO.13 シリアル通信(2) ←シリアルポートのオープンとクローズを説明
 NO.14 シリアル通信(3) ←シリアルポートの通信プロトコル、送受信バッファ、タイムアウトの設定
 NO.15 シリアル通信(4) ←シリアルポートの送受信方法を説明
・今回の場合は、
   シリアルポートのオープン → 存在有無チェック → シリアルポートのクローズ
 までを行えば良いようなので、シリアル通信(1)~(2) までを参照すれば良いと思います。

2)CreateFile関数でCOM10以上のCOMポートを使用する際の注意点

◎CreateFile関数(Win32API)でCOM10以上を使う場合の注意点
http://www.aofactory.net/log/eid328.html
・ここで、API関数「CreateFile」で指定するCOMポート名(COM1、COM2など)に「COM10」以上を使用
 する場合の問題点および対策が書かれています。
・指定するCOMポートのデバイス名の頭に "\\.\" を付ければ良いようです。
   VBAでの指定例: "COM10" の場合は、 "\\.\COM10" とする。

3)WindowsAPI利用でCOMポートの存在有無をチェックする方法

◎COMポートが存在するかどうかを調べるには? - OKWaveの過去ログより
http://okwave.jp/qa4033242.html
・ここで、API関数「CreateFile」が失敗した際に、同じくAPI関数「GetLastError」でエラーコードを見て
 COMポートの存在有無を調べる旨が書かれています。
注)ただし、VBAでは「GetLastError」を呼んでもエラーコードが得られない可能性があるので、下記4)
 の方法を採った方が良いようです。

4)VBA から Windows API を利用する方法など

◎Office VBA と Windows API - Microsoft MSDN より
http://msdn.microsoft.com/ja-jp/library/cc326057.aspx
・このページの「エラー情報の取得」の説明で、VBAからWindowsAPIを呼出した際のエラーコードの取得
 方法が書かれています。
・VBAからWindowsAPIのDLLを呼び出した際のエラー情報は、「GetLastError関数」では取得できない
 可能性があるので、VBAの場合は「Errオブジェクト」の「LastDLLErrorプロパティ」でエラーコードを取得
 すれば良いようです。
・今回の場合は、COMポートオープン時のエラーコード取得に、この方法が利用できると思います。

こんにちは。

Windowsのプログラム(VBA含む)から、COMポートを扱う場合は、WindowsAPI を使用すれば可能
だと思います。

COMポートの実装チェックには、WindowsAPI の「CreateFile」関数でCOMポートのオープンを実行
して、その関数の戻り値がエラーかどうかを見れば判断できると思います。
ただし、COMポートが実装されていてもエラーになるケース(既に使用中、使用不可に設定されて
いるなど)がありますので、その場合はエラーコードを取得してその値で「実装/非実装」を判断しな
いといけないと...続きを読む

Qbyte型をstring型として扱うには

今日の質問/マイページに反映されないので、再度の質問です。
windows2000-sp4/vb6-sp5環境です。ユニコードのデータをvbで直接入出力し、vb内でstring型で扱いたいとおもっています。今のところ、vbの入出力では、自動的にsjis/unicode変換がされるので、binaryで受け取り、string型にするのかなと思っています。byte型で受け取り、APIの"MoveMemory"("RtlMoveMemory")でstring型にcopyするのかなとは思っているのですが、うまくいきません。経験不足そのものです。vbでのbyte型とstring型双方向のbinaryな変換の方法をお教えください。

Aベストアンサー

dim s as string
dim b() as byte

'文字列 -> byte配列
b = s

'byte配列 -> 文字列
s = b


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報