From b3fa3bdb52011e2b0d0ac321f0012f6d522fa038 Mon Sep 17 00:00:00 2001 From: Oleg Broslavsky Date: Thu, 18 Jul 2019 18:38:41 +0700 Subject: [PATCH] Update README.md. Improve docs a bit --- README.md | 41 ++++++++++++++++++++++++++++++++++------- connection.go | 1 + decoder.go | 43 +++++++++++++++++++++++-------------------- doc.go | 23 ----------------------- example_test.go | 29 +++++++++++++++++++++++++++++ swbemservices.go | 1 + 6 files changed, 88 insertions(+), 50 deletions(-) create mode 100644 example_test.go diff --git a/README.md b/README.md index e63bf06..dbb6eb9 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,24 @@ Package wmi provides a WQL interface to Windows WMI. Note: It interfaces with WMI on the local machine, therefore it only runs on Windows. +## Fork Features +**Fork is fully compatibly with the original repo.** If not - please open an issue. + +New features introduced in fork: +- Go 1.11 modules support :) +- Improved decoder: + + support all basic types: all integer types, `float32`, + `string`, `bool`, `uintptr` and `time.Time` + + support slices and pointers to all basic types + + support decoding of structure fields (see [events example](./examples/events/main.go)) + + support structure tags + + support JSON-like interface for custom decoding + + suitable for decoding properties of any go-ole IDispatch object +- Ability to perform multiple queries in a single connection +- `SWbemServices.Get` + auto dereference of REF fields +- `SWbemServices.ExecNotificationQuery` support +- More other improvements described in [releases page](https://github.com/bi-zone/wmi/releases) + ## Example Print names of the currently running processes ```golang @@ -18,25 +36,23 @@ import ( "github.com/bi-zone/wmi" ) -// When we use `wmi.CreateQuery` the name of the struct should match querying -// WMI class name. -type Win32_Process struct { +type win32Process struct { PID uint32 `wmi:"ProcessId"` Name string UserField int `wmi:"-"` } func main() { - var dst []Win32_Process + var dst []win32Process - q := wmi.CreateQuery(&dst, "") + q := wmi.CreateQueryFrom(&dst, "Win32_Process", "") fmt.Println(q) if err := wmi.Query(q, &dst); err != nil { log.Fatal(err) } for _, v := range dst { - fmt.Println(v.PID, v.Name) + fmt.Printf("%6d\t%s\n", v.PID, v.Name) } } ``` @@ -57,4 +73,15 @@ BenchmarkQuery_SWbemConnection 5000 30099403 ns/op You could reproduce the results on your machine running: ```bash go test -run=NONE -bench=Query -benchtime=120s -``` \ No newline at end of file +``` + +## Versioning + +Project uses [semantic versioning](http://semver.org) for version numbers, which +is similar to the version contract of the Go language. Which means that the major +version will always maintain backwards compatibility with minor versions. Minor +versions will only add new additions and changes. Fixes will always be in patch. + +This contract should allow you to upgrade to new minor and patch versions without +breakage or modifications to your existing code. Leave a ticket, if there is breakage, +so that it could be fixed. diff --git a/connection.go b/connection.go index 90ad246..6d42c27 100644 --- a/connection.go +++ b/connection.go @@ -110,6 +110,7 @@ func (s *SWbemServicesConnection) Close() error { // More info about result unmarshalling is available in `Decoder.Unmarshal` doc. // // Query is performed using `SWbemServices.ExecQuery` method. +// // Ref: https://docs.microsoft.com/en-us/windows/desktop/wmisdk/swbemservices-execquery func (s *SWbemServicesConnection) Query(query string, dst interface{}) error { s.Lock() diff --git a/decoder.go b/decoder.go index a8e34fe..41bfc0b 100644 --- a/decoder.go +++ b/decoder.go @@ -91,14 +91,15 @@ var timeType = reflect.TypeOf(time.Time{}) // Unmarshal loads `ole.IDispatch` into a struct pointer. // N.B. Unmarshal supports only limited subset of structure field // types: -// - all signed and unsigned integers -// - time.Time -// - string -// - bool -// - float32 -// - a pointer to one of types above -// - a slice of one of thus types -// - structure types. +// - all signed and unsigned integers +// - uintptr +// - time.Time +// - string +// - bool +// - float32 +// - a pointer to one of types above +// - a slice of one of thus types +// - structure types. // // To unmarshal more complex struct consider implementing `wmi.Unmarshaler`. // For such types Unmarshal just calls `.UnmarshalOLE` on the @src object . @@ -116,22 +117,22 @@ var timeType = reflect.TypeOf(time.Time{}) // // Unmarshal allows to specify special COM-object property name or skip a field // using structure field tags, e.g. -// // Will be filled from property `Frequency_Object` -// FrequencyObject int wmi:"Frequency_Object"` +// // Will be filled from property `Frequency_Object` +// FrequencyObject int wmi:"Frequency_Object"` // -// // Will be skipped during unmarshalling. -// MyHelperField int wmi:"-"` +// // Will be skipped during unmarshalling. +// MyHelperField int wmi:"-"` // -// // Will be unmarshalled by CIM reference. -// // See `Dereferencer` for more info. -// Field Type `wmi:"FieldName,ref" -// Field2 Type `wmi:",ref" +// // Will be unmarshalled by CIM reference. +// // See `Dereferencer` for more info. +// Field Type `wmi:"FieldName,ref" +// Field2 Type `wmi:",ref" // // Unmarshal prefers tag value over the field name, but ignores any name collisions. // So for example all the following fields will be resolved to the same value. -// Field int -// Field1 int `wmi:"Field"` -// Field2 int `wmi:"Field"` +// Field int +// Field1 int `wmi:"Field"` +// Field2 int `wmi:"Field"` func (d Decoder) Unmarshal(src *ole.IDispatch, dst interface{}) (err error) { defer func() { // We use lots of reflection, so always be alert! @@ -254,7 +255,9 @@ var ( // tries to fit it inside a given structure field with some possible // conversions (e.g. possible integer conversions, string to int parsing // and others). -// This function handles all oleutil.VARIANT types exclude VT_UNKNOWN and VT_DISPATCH. +// +// This function handles all oleutil.VARIANT types except VT_UNKNOWN and +// VT_DISPATCH. func unmarshalSimpleValue(dst reflect.Value, value interface{}) error { switch val := value.(type) { case int8, int16, int32, int64, int: diff --git a/doc.go b/doc.go index ccaed5a..bb1362e 100644 --- a/doc.go +++ b/doc.go @@ -2,28 +2,5 @@ /* Package wmi provides a WQL interface for WMI on Windows. - -Example code to print names of running processes: - // When we use `wmi.CreateQuery` the name of the struct should match querying - // WMI class name. - type Win32_Process struct { - PID uint32 `wmi:"ProcessId"` - Name string - UserField int `wmi:"-"` - } - - func main() { - var dst []Win32_Process - - q := wmi.CreateQuery(&dst, "") - fmt.Println(q) - - if err := wmi.Query(q, &dst); err != nil { - log.Fatal(err) - } - for _, v := range dst { - fmt.Println(v.PID, v.Name) - } - } */ package wmi diff --git a/example_test.go b/example_test.go new file mode 100644 index 0000000..c461a5e --- /dev/null +++ b/example_test.go @@ -0,0 +1,29 @@ +package wmi_test + +import ( + "fmt" + "log" + + "github.com/bi-zone/wmi" +) + +// Structure with some fields of Win32_Process +type win32Process struct { + PID uint32 `wmi:"ProcessId"` // Field name differ from Win32_Process + Name string // Same name + UserField int `wmi:"-"` // Shouldn't affect WMI fields +} + +func Example_EnumerateRunningProcesses() { + var dst []win32Process + + q := wmi.CreateQueryFrom(&dst, "Win32_Process", "") + fmt.Println(q) + + if err := wmi.Query(q, &dst); err != nil { + log.Fatal(err) + } + for _, v := range dst { + fmt.Printf("%6d\t%s\n", v.PID, v.Name) + } +} diff --git a/swbemservices.go b/swbemservices.go index a114efa..19f14f5 100644 --- a/swbemservices.go +++ b/swbemservices.go @@ -91,6 +91,7 @@ func (s *SWbemServices) Close() error { // // By default, the local machine and default namespace are used. These can be // changed using connectServerArgs. See Ref. for more info. +// // Ref: https://docs.microsoft.com/en-us/windows/desktop/wmisdk/swbemlocator-connectserver func (s *SWbemServices) Query(query string, dst interface{}, connectServerArgs ...interface{}) (err error) { s.Lock()