.cplの名前

タグの編集
投稿者 ねこまっしぐら  (社会人) 投稿日時 2017/9/23 20:49:31
.cplの名前(というかタイトル? 要はmain.cpl->マウス)ってどうすれば取得出来るのでしょうか
レジストリには無いようですが…
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/26 05:34:32
cpl を起動した時のウィンドウ キャプションのことでしょうか。
自作の cpl ファイルもありえるわけですし、汎用的な方法は無いと思いますが…。

それとも、コントロール パネルに表示される項目名のことでしょうか。
であれば CPlApplet API はどうでしょう。
https://msdn.microsoft.com/ja-jp/library/cc422037.aspx
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/26 05:38:26
サンプルを書いてみました。

掲示板の 4000 文字制限に引っかかってしまったので、複数回に分けて投稿します。

Imports System.Runtime.InteropServices
Imports System.Text

Public Partial Class Form1
    Private Const CPL_DYNAMIC_RES As UInteger = 0UI
    Private Const CPL_INIT As UInteger = 1UI
    Private Const CPL_GETCOUNT As UInteger = 2UI
    Private Const CPL_INQUIRE As UInteger = 3UI
    Private Const CPL_NEWINQUIRE As UInteger = 8UI
    Private Const CPL_EXIT As UInteger = 7UI

    <StructLayout(LayoutKind.Sequential, Pack:=4)>
    Private Class CPLINFO
        Public idIcon As Integer
        Public idName As Integer
        Public idInfo As Integer
        Public lData As IntPtr
    End Class

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi, Pack:=4)>
    Private Class NEWCPLINFOA
        Public dwSize As Integer
        Public dwFlags As Integer
        Public dwHelpContext As Integer
        Public lData As IntPtr
        Public hIcon As IntPtr
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> Public szName As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=64)> Public szInfo As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> Public szHelpFile As String
    End Class

    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode, Pack:=4)>
    Private Class NEWCPLINFOW
        Public dwSize As Integer
        Public dwFlags As Integer
        Public dwHelpContext As Integer
        Public lData As IntPtr
        Public hIcon As IntPtr
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=32)> Public szName As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=64)> Public szInfo As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=128)> Public szHelpFile As String
    End Class
    Private Delegate Function CPlAppletDelegate(hwndCPl As IntPtr, uMsg As UInteger, lParam1 As IntPtr, lParam2 As IntPtr) As Integer

    Private Declare Unicode Function LoadLibrary Lib "kernel32" Alias "LoadLibraryW" (lpFileName As StringAs IntPtr
    Private Declare Ansi Function GetProcAddress Lib "kernel32" (hModule As IntPtr, lpProcName As StringAs IntPtr
    Private Declare Unicode Function FreeLibrary Lib "kernel32" (hModule As IntPtr) As Boolean
    Private Declare Unicode Function LoadString Lib "user32" Alias "LoadStringW" (hInstance As IntPtr, uID As Integer, lpBuffer As StringBuilder, nBufferMax As IntegerAs Integer
End Class
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/26 05:40:19
続きです。

Imports System.Runtime.InteropServices
Imports System.Text
Public Partial Class Form1
    Private WithEvents ComboBox1 As ComboBox
    Private WithEvents ListBox1 As ListBox

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Controls.Clear()

        Padding = New Padding(3)

        ListBox1 = New ListBox()
        ListBox1.Dock = DockStyle.Fill
        ListBox1.Margin = New Padding(4)
        ListBox1.IntegralHeight = False
        ListBox1.TabIndex = 1
        Controls.Add(ListBox1)

        ComboBox1 = New ComboBox()
        ComboBox1.Dock = DockStyle.Top
        ComboBox1.DropDownStyle = ComboBoxStyle.DropDownList
        ComboBox1.TabIndex = 0
        Controls.Add(ComboBox1)

        ComboBox1.DataSource = My.Computer.FileSystem.GetFiles(Environment.SystemDirectory, FileIO.SearchOption.SearchTopLevelOnly, "*.cpl").ToArray()
        ComboBox1.SelectedIndex = -1
    End Sub

    Private Function LoadResString(hInstance As IntPtr, uID As IntegerAs String
        Dim buf As New StringBuilder(4096)
        Dim size As Integer = LoadString(hInstance, uID, buf, buf.Capacity)
        Dim dwSize As Integer = Math.Min(size, buf.Length)
        If dwSize > 0 Then
            Return buf.ToString(0, dwSize)
        Else
            Return ""
        End If
    End Function
End Class
投稿者 (削除されました)  () 投稿日時 2017/9/26 05:45:23
(削除されました)
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/26 05:53:55
これで最後。

半角空白4文字のインデントだと 4000文字上限に阻まれたので、
全角空白1文字のインデントにして、文字数を削減させています。


Imports System.Runtime.InteropServices
Imports System.Text
Public Partial Class Form1
  Private Sub ComboBox1_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles ComboBox1.SelectionChangeCommitted
  ListBox1.Items.Clear()

   Dim cplFile As String = CStr(ComboBox1.SelectedItem)
   If String.IsNullOrEmpty(cplFile) Then
    Return
   End If
  ListBox1.Items.Add(System.IO.Path.GetFileName(cplFile))

   Dim hModule = LoadLibrary(cplFile)
   Dim szCPLINFO = Marshal.SizeOf(GetType(CPLINFO))
   Dim szNEWCPLINFOW = Marshal.SizeOf(GetType(NEWCPLINFOW))
   Dim szNEWCPLINFOA = Marshal.SizeOf(GetType(NEWCPLINFOA))
   Try
    Dim hCPlApplet = GetProcAddress(hModule, "CPlApplet")
    If hCPlApplet = IntPtr.Zero Then
    ListBox1.Items.Add("は CPlApplet 関数をエクスポートしていません。")
     Return
   End If
      Dim CPlApplet = DirectCast(Marshal.GetDelegateForFunctionPointer(hCPlApplet, GetType(CPlAppletDelegate)), CPlAppletDelegate)
    If CPlApplet(Handle, CPL_INIT, IntPtr.Zero, IntPtr.Zero) = 0 Then
    ListBox1.Items.Add("のロードに失敗しました。")
     Return
    End If

    Dim count As Integer = CPlApplet(Handle, CPL_GETCOUNT, IntPtr.Zero, IntPtr.Zero)
   ListBox1.Items.Add("には、" & CStr(count) & "個のアプレットがあります")

    For n = 0 To count - 1
    ListBox1.Items.Add("===== Applet #" & CStr(n) & " =====")

    ListBox1.Items.Add("--- CPL_INQUIRE で取得 ---")
     Dim pCPlInfo = Marshal.AllocCoTaskMem(szCPLINFO)
     For p = 0 To szCPLINFO - 1
     Marshal.WriteByte(pCPlInfo, p, 0)
     Next
    CPlApplet(Handle, CPL_INQUIRE, New IntPtr(n), pCPlInfo)
     Dim oCPlInfo = DirectCast(Marshal.PtrToStructure(pCPlInfo, GetType(CPLINFO)), CPLINFO)
    Marshal.FreeCoTaskMem(pCPlInfo)
    ListBox1.Items.Add("CPLINFO: idIcon=" & CStr(oCPlInfo.idIcon))
        ListBox1.Items.Add("CPLINFO: idName=" & CStr(oCPlInfo.idName) & ", """ & LoadResString(hModule, oCPlInfo.idName) & """")
        ListBox1.Items.Add("CPLINFO: idInfo=" & CStr(oCPlInfo.idInfo) & ", """ & LoadResString(hModule, oCPlInfo.idInfo) & """")
    ListBox1.Items.Add("CPLINFO: lData=" & oCPlInfo.lData.ToString())

    ListBox1.Items.Add("--- CPL_NEWINQUIRE で取得 ---")
     Dim pNewCPlInfo = Marshal.AllocCoTaskMem(szNEWCPLINFOW)
     For p = 0 To szNEWCPLINFOW - 1
     Marshal.WriteByte(pNewCPlInfo, p, 0)
     Next
    CPlApplet(Handle, CPL_NEWINQUIRE, New IntPtr(n), pNewCPlInfo)
     Dim dwSize = Marshal.ReadInt32(pNewCPlInfo, 0)
     Select Case dwSize
      Case 0
      ListBox1.Items.Add("NEWCPLINFO: 取得できませんでした。")
      Case szNEWCPLINFOW
       Dim oNewCPlInfoW = DirectCast(Marshal.PtrToStructure(pNewCPlInfo, GetType(NEWCPLINFOW)), NEWCPLINFOW)
      ListBox1.Items.Add("NEWCPLINFOW: hIcon=" & oNewCPlInfoW.hIcon.ToString())
      ListBox1.Items.Add("NEWCPLINFOW: szName=""" & If(oNewCPlInfoW.szName, "").Split(Char.MinValue)(0) & """")
      ListBox1.Items.Add("NEWCPLINFOW: szInfo=""" & If(oNewCPlInfoW.szInfo, "").Split(Char.MinValue)(0) & """")
      ListBox1.Items.Add("NEWCPLINFOW: lpData=" & oNewCPlInfoW.lData.ToString())
      Case szNEWCPLINFOA
       Dim oNewCPlInfoA = DirectCast(Marshal.PtrToStructure(pNewCPlInfo, GetType(NEWCPLINFOA)), NEWCPLINFOA)
      ListBox1.Items.Add("NEWCPLINFOA: hIcon=" & oNewCPlInfoA.hIcon.ToString())
      ListBox1.Items.Add("NEWCPLINFOA: szName=""" & If(oNewCPlInfoA.szName, "").Split(Char.MinValue)(0) & """")
      ListBox1.Items.Add("NEWCPLINFOA: szInfo=""" & If(oNewCPlInfoA.szInfo, "").Split(Char.MinValue)(0) & """")
      ListBox1.Items.Add("NEWCPLINFOA: lpData=" & oNewCPlInfoA.lData.ToString())
      Case Else
      ListBox1.Items.Add("NEWCPLINFO: 不明なサイズ:" & CStr(dwSize))
     End Select
    Marshal.FreeCoTaskMem(pNewCPlInfo)
    Next
   CPlApplet(Handle, CPL_EXIT, IntPtr.Zero, IntPtr.Zero)
   Finally
   FreeLibrary(hModule)
   End Try
  End Sub
End Class
投稿者 ねこまっしぐら  (社会人) 投稿日時 2017/9/26 10:22:51
魔界の仮面弁士様、回答ありがとうございます
しかもソースまで…

試してみましたが20個中12個まで項目名が取れました
ただ「序数381がダイナミックライブラリcomctl32.dllから見つかりませんでした」ってエラーが出ますが…

ともあれありがとうございました
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2017/9/28 10:38:11
> ただ「序数381がダイナミックライブラリcomctl32.dllから見つかりませんでした」ってエラーが出ますが…

その DLL を呼び出している別の DLL が、何らかの
バージョン不整合を起こしているのではないでしょうか。

『dumpbin /exports C:\Windows\SysWOW64\comctl32.dll』コマンド等で
手元の DLL を確認してみましたが、いずれも序数381は見当たりませんでしたし。

・32bit 版 comctl32.dll (ファイルバージョン 5.82.16291.0) 572,456 バイト
・32bit 版 comctl32.dll (ファイルバージョン 5.82.7601.18837) 530,432 バイト
・64bit 版 comctl32.dll (ファイルバージョン 5.82.16291.0) 662,056 バイト
・64bit 版 comctl32.dll (ファイルバージョン 5.82.7601.18837) 633,856 バイト


そのエラーの呼び出し元プロセスが分かりませんが、もしかしたら
 (1) EXE のプロパティの「互換モード」で下位バージョンの OS を選択してみる
 (2) EXE を「管理者として実行」モードで起動してみる
 (3) Windows を修復セットアップしなおしてみる
などで軽減されるかもしれません。
投稿者 ねこまっしぐら  (社会人) 投稿日時 2017/9/28 15:06:20
重ね重ねありがとうございます

その後1つづつ読み込ませずに試したところエラー出してたのはMMSYS.cplでしたので
それだけ読み飛ばすようにしたらokでした

ありがとうございました