.cplの名前
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/9/26 05:34:32
cpl を起動した時のウィンドウ キャプションのことでしょうか。
自作の cpl ファイルもありえるわけですし、汎用的な方法は無いと思いますが…。
それとも、コントロール パネルに表示される項目名のことでしょうか。
であれば CPlApplet API はどうでしょう。
https://msdn.microsoft.com/ja-jp/library/cc422037.aspx
自作の cpl ファイルもありえるわけですし、汎用的な方法は無いと思いますが…。
それとも、コントロール パネルに表示される項目名のことでしょうか。
であれば CPlApplet API はどうでしょう。
https://msdn.microsoft.com/ja-jp/library/cc422037.aspx
投稿者 魔界の仮面弁士  (社会人)
投稿日時
2017/9/26 05:38:26
サンプルを書いてみました。
掲示板の 4000 文字制限に引っかかってしまったので、複数回に分けて投稿します。
掲示板の 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 String) As IntPtr
Private Declare Ansi Function GetProcAddress Lib "kernel32" (hModule As IntPtr, lpProcName As String) As 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 Integer) As 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 Integer) As 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文字のインデントにして、文字数を削減させています。
半角空白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から見つかりませんでした」ってエラーが出ますが…
ともあれありがとうございました
しかもソースまで…
試してみましたが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 を修復セットアップしなおしてみる
などで軽減されるかもしれません。
その 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でした
ありがとうございました
その後1つづつ読み込ませずに試したところエラー出してたのはMMSYS.cplでしたので
それだけ読み飛ばすようにしたらokでした
ありがとうございました
レジストリには無いようですが…