VBネタ:WMIのWin32_Printerで他マシンのプリンタ情報取得

えーっと、「ネットワーク上のコンピュータから

プリンタ情報を取得したいのだが...」っつーことで

「こりゃWMIだろ」( ̄− ̄)

ということで調べるとWin32_Printerを使うことで

取得が可能であることが判明した。

全部のプロパティを吐き出させてみると、

以外や以外にPaperNoからドライバ情報まで

Debug.Printが溢れんばかりに吐き出してました(゜∀゜)ウヒャ

で、そのテスト版がρ(・д・*)コレ


Sub Test_WMI_GetPrinterInfo()
Dim strComputerName As String
Dim strUserName As String
Dim strPassword As String
Dim objLocator As New WbemScripting.SWbemLocator
Dim objWMIService As WbemScripting.SWbemServices
Dim objWin32_Printer As WbemScripting.SWbemObjectSet
Dim objPrinter As WbemScripting.SWbemObject
Dim objProperty As WbemScripting.SWbemProperty
Dim strMsg As String
Dim i As Integer

strComputerName = "MyComputer"
strUserName = "Administrator"
strPassword = "hogehoge"

Set objWMIService = objLocator.ConnectServer(strComputerName, , strUserName, strPassword)
Set objWin32_Printer = objWMIService.InstancesOf("Win32_Printer")
For Each objPrinter In objWin32_Printer
strMsg = strMsg & "-------------------------------------" & vbCrLf
For Each objProperty In objPrinter.Properties_
If IsArray(objProperty.Value) Then
For i = LBound(objProperty.Value) To UBound(objProperty.Value)
strMsg = strMsg & "[" & objProperty.Name & "](" & i & ")=" & objProperty.Value(i) & vbCrLf
Next
Else
strMsg = strMsg & "[" & objProperty.Name & "]=" & objProperty.Value & vbCrLf
End If
Next
Next

Debug.Print strMsg

End Sub

SQLServerネタ

多忙かつ多忘により(?)に久々の更新になるのだが、
今まで出来ないと思っていた、SQLServerでのネットワーク越しの
復元orバックアップについて実は出来ることが判明した...
具体的な方法がρ(・д・*)コレ


SQLServerでネットワークドライブからの復元(バックアップ)を行う方法について>
[ポイント]
SQLServerはサービスのアカウント権限でネットワーク接続を試みる

[具体例]
マシン名
COMP_SRC
COMP_DES

役割
COMP_SRC=復元しようとするマシン
COMP_DES=復元するバックアップファイルが置いてあるマシン

概要
COMP_SRCのSQLServerから復元するときにCOMP_DESにある
バックアップファイルを指定して復元を行う。

設定
1.COMP_SRCにWindowsユーザ「SQLAdmin」を追加
 *SQLAdminは任意であり、ここでは仮で名前付けします。
2.追加したSQLAdminにWindowsグループ「Administrators」を追加
 *これはサービスアカウントが行う役割が不明であることから
  万が一に備えて追加しておきます。
3.COMP_SRCのSQLServerでサービス開始アカウントを01で設定した
 ユーザに変更します。
4.COMP_DESにWindowsユーザ「SQLAdmin」を追加
 *権限はUsersグループのままでも問題ありません。
5.COMP_DESのバックアップファイルがあるフォルダを
 共有し、COMP_SRCは該当フォルダをネットワークドライブに
 割り当てします。(ここではXドライブとします)
6.COMP_SRCのSQLServerから復元を行うとデバイス(ファイル)の指定で
 Xドライブが出現し、そこから復元が可能となります。

VBネタ


ふと、VB(もしくはVBA)の[ツール] --> [参照設定]で

何があるのかを見るために



テキストで出力した「参照設定」の一覧がほしいな〜



ってただ単にオブジェクトの遊び道具を探すためである。

で、調べて見たらWMIで出来ることが判明した。

ほんでもって出来たのがρ(・д・*)コレ


Sub Test_WriteTypeLib()
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_PERFORMANCE_DATA = &H80000004
Const HKEY_CURRENT_CONFIG = &H80000005
Const HKEY_DYN_DATA = &H80000006

Const KEY_QUERY_VALUE = &H1
Const KEY_SET_VALUE = &H2
Const KEY_CREATE_SUB_KEY = &H4
Const KEY_ENUMERATE_SUB_KEYS = &H8
Const KEY_NOTIFY = &H10
Const KEY_CREATE_LINK = &H20
Const DELETE = &H10000
Const READ_CONTROL = &H20000
Const WRITE_DAC = &H40000
Const WRITE_OWNER = &H80000

Const REG_KEY As String = "TypeLib"

Dim strComputerName As String
Dim strUserName As String
Dim strPassword As String
Dim objWMILocator As New WbemScripting.SWbemLocator
Dim objWMIService As WbemScripting.SWbemServices
Dim objWMIStdRegProv As WbemScripting.SWbemObject
Dim aryKeys As Variant
Dim arySubKeys As Variant
Dim varResult As Variant
Dim strEnumReference As String
Dim i As Integer
Dim j As Integer
Dim fsoSys As New Scripting.FileSystemObject
Dim txsSrc As Scripting.TextStream
Dim strOutput As String
Dim dblStart As Double
Dim rstEnumReference As New ADODB.Recordset

dblStart = Timer()

strComputerName = "."
strUserName = ""
strPassword = ""
strOutput = "F:\Temp\EnumReference.txt"

Set objWMIService = objWMILocator.ConnectServer(strComputerName, _
"root\default", _
strUserName, _
strPassword)
Set objWMIStdRegProv = objWMIService.Get("StdRegProv")

'HKEY_CLASSES_ROOT\TypeLib
Call objWMIStdRegProv.EnumKey(HKEY_CLASSES_ROOT, _
REG_KEY, _
aryKeys)

'名前の昇順用にADODB.Recordsetを使用する
rstEnumReference.Fields.Append "vchReferenceName", adVarChar, 255

If IsArray(aryKeys) Then
With rstEnumReference
.Open

'参照設定の取得
For i = LBound(aryKeys) To UBound(aryKeys)
Call objWMIStdRegProv.EnumKey(HKEY_CLASSES_ROOT, _
REG_KEY & "\" & aryKeys(i), _
arySubKeys)

If IsArray(arySubKeys) Then
For j = LBound(arySubKeys) To UBound(arySubKeys)
objWMIStdRegProv.GetStringValue HKEY_CLASSES_ROOT, _
REG_KEY & "\" & aryKeys(i) & "\" & arySubKeys(j), _
"", _
varResult
If Not IsNull(varResult) Then
.AddNew
.Fields("vchReferenceName") = varResult
.Update
End If
Next
End If
Next

'並び替えた状態でのファイル出力
If .RecordCount > 0 Then
Set txsSrc = fsoSys.CreateTextFile(strOutput)

.MoveFirst
.Sort = "vchReferenceName ASC"
Do Until .EOF
txsSrc.WriteLine .Fields("vchReferenceName")

.MoveNext
Loop
txsSrc.Close
End If

.Close
End With
End If

Set objWMILocator = Nothing
Set objWMIService = Nothing
Set objWMIStdRegProv = Nothing
Set fsoSys = Nothing
Set txsSrc = Nothing

MsgBox "参照設定一覧の出力が完了しました。" & vbCrLf & _
"処理時間:" & Format$(Timer() - dblStart, "0.00秒")
End Sub

SQLSererネタ:WHERE句にユーザー関数はご法度の巻き

SQLServerの中古1年生である、わたしは「処理時間がかかりすぎ」
ということで、色々調査をしていた時にSQLエリアナライザに
[実行プラン]なるものがあることに気がつき、そのおかげで
ボトルネックを解消してから、やみつき状態に。
ある時、ボトルネックを調査していたら、あるパターンの
ネックがあることが判明した。それは、
「WHERE句にユーザー定義関数がある場合」であった。
下記のテストを見て頂こう。
[テーブル]
CREATE TABLE [TAB_Test_Where_Function] (
[Col1] [varchar] (50) COLLATE Japanese_BIN NULL
) ON [PRIMARY]

[ユーザー定義関数]
CREATE FUNCTION UDF_Test_Where_Function(@Value AS INT)
RETURNS INT
AS
BEGIN
SET @Value = @Value + 1
RETURN (@Value)
END

[ストアドプロシージャ]
CREATE PROCEDURE PRC_Test_Where_Function
AS
SELECT * FROM TAB_Test_Where_Function WHERE Col1 = dbo.UDF_Test_Where_Function(1)

上記のテスト環境を作成した後に、[TAB_Test_Where_Function].[Col1]に
データを入れる。
[Col1]
100
200
300
とりあえず3件入れて、デバッグをしてみた。
すると、

ユ ー ザ ー 定 義 関 数 を 3 回 通 っ て い る

ではないかぁーΣ(゜д゜lll)ガーン
さらに2件増やしてテストすると、5回通っていることを確認した。
つまり、WHERE句にユーザー定義関数を設定すると、

デ ー タ 件 数 分 ユ ー ザ ー 定 義 関 数 
 を 通 っ て し ま う

っちゅーこっちゃ。Σ(゜д゜)オイオイ
というよりも、わたし自身がユーザー定義関数を勘違いしている
可能性が大である。てっきり「ユーザー関数は1回しか通らない」
と思い込んでいたのが敗因かと思われる。
ちなみに今回ボトルネックだったパターンは、

DELETE FROM TAB_Hoge WHERE Col = UDF_MaeZero(@intValue, 12)

というケースだった。UDF_MaeZero(@intValue, 12)の部分は固定で良い
ので、

SET @vchValue = UDF_MaeZero(@intValue, 12)
DELETE FROM TAB_Hoge WHERE Col = @vchValue

というパターンでボトルネックを回避できた。
使いどころや勘違いに要・注意。ウフ♪(* ̄ー ̄)v
と思った今日この頃。SQLServerは奥が深いのぉ。