Skip to content

Commit

Permalink
Update README.md. Improve docs a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
yalegko committed Jul 18, 2019
1 parent 9392c71 commit b3fa3bd
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 50 deletions.
41 changes: 34 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
}
```
Expand All @@ -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
```
```

## 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.
1 change: 1 addition & 0 deletions connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
43 changes: 23 additions & 20 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 .
Expand All @@ -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!
Expand Down Expand Up @@ -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:
Expand Down
23 changes: 0 additions & 23 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
29 changes: 29 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
1 change: 1 addition & 0 deletions swbemservices.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down

0 comments on commit b3fa3bd

Please sign in to comment.