トップ回答者
重複起動のチェック時のvbUnicodeについて

質問
-
いつも参考にさせていただいております。
重複チェックの際に正しいプロセス名が取ってこれない件について、ご教授願いたいと思います。
環境はWindows 2003 Server , VB.NET です。
当初はVB6で動いていたもののため、
関数「fGetProcessName」内の、
sString = Left(StrConv(System.Text.UnicodeEncoding.Unicode.GetString(tModuleBaseName), vbUnicode), lRetValue)
が有効でした。
やりたいことは、同じプロセス名が存在したとき、「重複エラーです」というメッセージを出すことです。
VB.NETになってvbUnicodeが使えなくなったため、変数
Dim eUnicode As Encoding = UnicodeEncoding.Unicode
Dim unicodeBytes As Byte()
Dim unicodeString As Stringを追加し、
unicodeString = System.Text.UnicodeEncoding.Unicode.GetString(tModuleBaseName)
unicodeBytes = eUnicode.GetBytes(unicodeString)
Dim unicodeChars(eUnicode.GetCharCount(unicodeBytes, 0, unicodeBytes.Length)) As Char
eUnicode.GetChars(unicodeBytes, 0, unicodeBytes.Length, unicodeChars, 0)
sString = unicodeCharsfGetProcessName = sString
という行に書き換えました。それでも、
fGetProcessName(tProcesses(i))
の行で必要なプロセス名を取得することができておりません。
Byte -> Stringへの変換がうまくいっていないように思えます。
コードは以下のとおりです。
********************************************************************
Public Function pfRunModule(ByVal sModuleName As String) As Boolean
'-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
'関数名:pfRunModule
'引数 :モジュール名
'戻り値:正常終了/異常終了
'概要 :引数のモジュールを起動する 既に起動している場合、手前に表示する
'-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
Const sFunctionName As String = "pfRunModule"Dim tProcesses(1023) As Integer 'プロセス配列
Dim lNeeded As Integer 'プロセス配列サイズ
Dim lProcesses As Integer 'プロセス数
Dim lWnd As Integer 'ウィンドウハンドル
Dim i As Integer 'ループカウンタ
Dim la As Integer'関数の戻り値を初期化する
pfRunModule = False
''プロセスを列挙する
lRetValue = EnumProcesses(tProcesses(0), UBound(tProcesses), lNeeded)
'プロセス数を取得する
lProcesses = lNeeded / 4
'取得したプロセスの分、ループする
For i = 0 To lProcesses - 1
'モジュールが存在すれば終了する
If fGetProcessName(tProcesses(i)) = sModuleName Then
Call MsgBox("重複起動です", MsgBoxStyle.Information + MsgBoxStyle.OkOnly, "9999")
Exit Function
End If
Next i
'モジュールが存在しなければ起動する
Call Shell(My.Application.Info.DirectoryPath & "\" & sModuleName, AppWinStyle.NormalFocus)
'正常終了する
pfRunModule = True********************************************************************
Private Function fGetProcessName(ByVal lProcessID As Integer) As String
'-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
'関数名:fGetProcessName
'引数 :プロセスID
'戻り値:モジュールベース名
'概要 :引数のプロセスIDでモジュールベース名を取得する
'-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+Const sFunctionName As String = "fGetProcessName"
Dim hProcess As Integer 'プロセスハンドル
Dim hModules(1023) As Integer 'モジュールハンドル配列
Dim lModules As Integer 'モジュール数
Dim lNeeded As Integer 'モジュール配列サイズ
Dim tModuleBaseName(255) As Byte 'モジュールベース名バッファ
Dim tModuleFileName(255) As Byte 'モジュールファイル名バッファ
Dim sString As String'***** VB6→.net2005 ADD START *****
Dim eUnicode As Encoding = UnicodeEncoding.Unicode
Dim unicodeBytes As Byte()
Dim unicodeString As String
'***** VB6→.net2005 ADD END *****'プロセスをオープンする
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, False, lProcessID)
If hProcess <> 0 Then
'モジュールを列挙する
If EnumProcessModules(hProcess, hModules(0), UBound(hModules), lNeeded) <> 0 Then
'モジュール数を取得する
lModules = lNeeded / 4
'モジュールベース名を取得する
lRetValue = GetModuleBaseName(hProcess, hModules(0), tModuleBaseName(0), UBound(tModuleBaseName))
'***** VB6→.net2005 UPD START *****
'sString = Left(StrConv(System.Text.UnicodeEncoding.Unicode.GetString(tModuleBaseName), vbUnicode), lRetValue)unicodeString = System.Text.UnicodeEncoding.Unicode.GetString(tModuleBaseName)
unicodeBytes = eUnicode.GetBytes(unicodeString)Dim unicodeChars(eUnicode.GetCharCount(unicodeBytes, 0, unicodeBytes.Length)) As Char
eUnicode.GetChars(unicodeBytes, 0, unicodeBytes.Length, unicodeChars, 0)
sString = unicodeChars'***** VB6→.net2005 UPD END *****
fGetProcessName = sString
End If
End If
'オープンしたプロセスをクローズする
Call CloseHandle(hProcess)End Function
**********************************************************************************
Left(StrConv(System.Text.UnicodeEncoding.Unicode.GetString(tModuleBaseName), vbUnicode), lRetValue)
の代わりになるVB.NETでのコードはどのようなものなのでしょうか。
MSDNのオンラインヘルプやあちこちを参照したのですが、見当たりませんでした。
お力をお貸しください。
よろしくお願いいたします。
回答
-
VB2005 なら、アプリケーションフレームワークを有効にすればほとんど書くことがなくなりますが。
-
外池と申します。
お提示いただいたコードで、Byteの配列にはなんらかのデータが得られているようですが、このByteの配列の中身を覗いて見られてはいかがですか? プロセス名ですから大した長さではなく、ASCIIのコード表と照らし合わせてみれば、どんな形で(ASCIIか、UNICODEか、など)データが得られているか一目瞭然だと思います。
その上で(どんなエンコード方式で格納されているかがわかったら)、
System.Text名前空間のEncodingクラスのGetStringメソッドを使えば、Byteの配列からお望みの文字列を得ることができるはずです。
-
無理にAPIを使ってVB6と同じロジックを再現しなくても、Threading.Mutexでチェックすればいいような気もします。
@IT:.NET TIPS Windowsアプリケーションの多重起動を禁止するには? - C# VB.NET Windowsフォーム
-
がねーしゃ さんからの引用 引数のモジュールを起動する 既に起動している場合、手前に表示する
Process.GetProcessesByNameで置き換えできませんか?
http://msdn2.microsoft.com/ja-jp/library/z3w4xdc9.aspx
http://jeanne.wankuma.com/tips/process/previnstance.html
がねーしゃ さんからの引用 引数のプロセスIDでモジュールベース名を取得する
Process.GetProcessByIdで置き換えできませんか?
http://msdn2.microsoft.com/ja-jp/library/76fkb36k.aspx
http://jeanne.wankuma.com/tips/process/getprocessbyid.html
これらのメソッドで必ずしも置き換えできるとは限りませんが、関数コメントを見る限りは使えそうかなと思いました。
すべての返信
-
VB2005 なら、アプリケーションフレームワークを有効にすればほとんど書くことがなくなりますが。
-
外池と申します。
お提示いただいたコードで、Byteの配列にはなんらかのデータが得られているようですが、このByteの配列の中身を覗いて見られてはいかがですか? プロセス名ですから大した長さではなく、ASCIIのコード表と照らし合わせてみれば、どんな形で(ASCIIか、UNICODEか、など)データが得られているか一目瞭然だと思います。
その上で(どんなエンコード方式で格納されているかがわかったら)、
System.Text名前空間のEncodingクラスのGetStringメソッドを使えば、Byteの配列からお望みの文字列を得ることができるはずです。
-
無理にAPIを使ってVB6と同じロジックを再現しなくても、Threading.Mutexでチェックすればいいような気もします。
@IT:.NET TIPS Windowsアプリケーションの多重起動を禁止するには? - C# VB.NET Windowsフォーム
-
がねーしゃ さんからの引用 引数のモジュールを起動する 既に起動している場合、手前に表示する
Process.GetProcessesByNameで置き換えできませんか?
http://msdn2.microsoft.com/ja-jp/library/z3w4xdc9.aspx
http://jeanne.wankuma.com/tips/process/previnstance.html
がねーしゃ さんからの引用 引数のプロセスIDでモジュールベース名を取得する
Process.GetProcessByIdで置き換えできませんか?
http://msdn2.microsoft.com/ja-jp/library/76fkb36k.aspx
http://jeanne.wankuma.com/tips/process/getprocessbyid.html
これらのメソッドで必ずしも置き換えできるとは限りませんが、関数コメントを見る限りは使えそうかなと思いました。
-
こんにちは。中川俊輔 です。
皆様、大変参考になる回答ありがとうございます。
がねーしゃさん、フォーラムのご利用ありがとうございます。
その後いかがでしょうか?
勝手ながら問題解決に有効と思われる回答へ回答済みチェックをつけさせていただきました。
追加の質問等あればぜひ投稿してください!
回答済みチェックが付くことにより、有用な情報を探している方が情報を見つけやすくなります。
問題解決につながる回答があった場合は、なるべく回答済みボタンを押してチェックを付けてください。がねーしゃさんはチェックを解除することもできますので、ご確認ください。
それでは!