func getFriendlyName(portname string) string { // this method panics a lot and i'm not sure why, just catch // the panic and return empty list defer func() { if e := recover(); e != nil { // e is the interface{} typed-value we passed to panic() log.Println("Got panic: ", e) // Prints "Whoops: boom!" } }() var friendlyName string // init COM, oh yeah ole.CoInitialize(0) defer ole.CoUninitialize() unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator") defer unknown.Release() wmi, _ := unknown.QueryInterface(ole.IID_IDispatch) defer wmi.Release() // service is a SWbemServices serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer") service := serviceRaw.ToIDispatch() defer service.Release() // result is a SWBemObjectSet //pname := syscall.StringToUTF16("SELECT * FROM Win32_PnPEntity where Name like '%" + "COM35" + "%'") pname := "SELECT * FROM Win32_PnPEntity where Name like '%" + portname + "%'" resultRaw, _ := oleutil.CallMethod(service, "ExecQuery", pname) result := resultRaw.ToIDispatch() defer result.Release() countVar, _ := oleutil.GetProperty(result, "Count") count := int(countVar.Val) for i := 0; i < count; i++ { // item is a SWbemObject, but really a Win32_Process itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) item := itemRaw.ToIDispatch() defer item.Release() asString, _ := oleutil.GetProperty(item, "Name") println(asString.ToString()) friendlyName = asString.ToString() } return friendlyName }
func readExample(fileName string, excel, workbooks *ole.IDispatch) { workbook, err := oleutil.CallMethod(workbooks, "Open", fileName) if err != nil { log.Fatalln(err) } defer workbook.ToIDispatch().Release() sheets := oleutil.MustGetProperty(excel, "Sheets").ToIDispatch() sheetCount := (int)(oleutil.MustGetProperty(sheets, "Count").Val) fmt.Println("sheet count=", sheetCount) sheets.Release() worksheet := oleutil.MustGetProperty(workbook.ToIDispatch(), "Worksheets", 1).ToIDispatch() defer worksheet.Release() for row := 1; row <= 2; row++ { for col := 1; col <= 5; col++ { cell := oleutil.MustGetProperty(worksheet, "Cells", row, col).ToIDispatch() val, err := oleutil.GetProperty(cell, "Value") if err != nil { break } fmt.Printf("(%d,%d)=%+v toString=%s\n", col, row, val.Value(), val.ToString()) cell.Release() } } }
func (c *AdodbConn) prepare(ctx context.Context, query string) (driver.Stmt, error) { unknown, err := oleutil.CreateObject("ADODB.Command") if err != nil { return nil, err } s, err := unknown.QueryInterface(ole.IID_IDispatch) if err != nil { return nil, err } _, err = oleutil.PutProperty(s, "ActiveConnection", c.db) if err != nil { return nil, err } _, err = oleutil.PutProperty(s, "CommandText", query) if err != nil { return nil, err } _, err = oleutil.PutProperty(s, "CommandType", 1) if err != nil { return nil, err } _, err = oleutil.PutProperty(s, "Prepared", true) if err != nil { return nil, err } val, err := oleutil.GetProperty(s, "Parameters") if err != nil { return nil, err } return &AdodbStmt{c, s, val.ToIDispatch(), nil}, nil }
func main() { ole.CoInitialize(0) unknown, _ := oleutil.CreateObject("Outlook.Application") outlook, _ := unknown.QueryInterface(ole.IID_IDispatch) ns := oleutil.MustCallMethod(outlook, "GetNamespace", "MAPI").ToIDispatch() folder := oleutil.MustCallMethod(ns, "GetDefaultFolder", 10).ToIDispatch() contacts := oleutil.MustCallMethod(folder, "Items").ToIDispatch() count := oleutil.MustGetProperty(contacts, "Count").Value().(int32) for i := 1; i <= int(count); i++ { item, err := oleutil.GetProperty(contacts, "Item", i) if err == nil && item.VT == ole.VT_DISPATCH { if value, err := oleutil.GetProperty(item.ToIDispatch(), "FullName"); err == nil { fmt.Println(value.Value()) } } } oleutil.MustCallMethod(outlook, "Quit") }
func oleInt64(item *ole.IDispatch, prop string) (int64, error) { v, err := oleutil.GetProperty(item, prop) if err != nil { return 0, err } defer v.Clear() i := int64(v.Val) return i, nil }
func (rc *AdodbRows) Columns() []string { if rc.nc != len(rc.cols) { unknown, err := oleutil.GetProperty(rc.rc, "Fields") if err != nil { return []string{} } fields := unknown.ToIDispatch() defer fields.Release() val, err := oleutil.GetProperty(fields, "Count") if err != nil { return []string{} } rc.nc = int(val.Val) rc.cols = make([]string, rc.nc) for i := 0; i < rc.nc; i++ { var varval ole.VARIANT varval.VT = ole.VT_I4 varval.Val = int64(i) val, err := oleutil.CallMethod(fields, "Item", &varval) if err != nil { return []string{} } item := val.ToIDispatch() if err != nil { return []string{} } name, err := oleutil.GetProperty(item, "Name") if err != nil { return []string{} } rc.cols[i] = name.ToString() item.Release() } } return rc.cols }
func (s *AdodbStmt) NumInput() int { if s.b != nil { return len(s.b) } _, err := oleutil.CallMethod(s.ps, "Refresh") if err != nil { return -1 } val, err := oleutil.GetProperty(s.ps, "Count") if err != nil { return -1 } c := int(val.Val) return c }
// NOTE: This function will panic if called with high frequency (we should throttle the polling - probably caused by slow OLE calls that can't be parallel.. sigh ;)) func GetSerialPortList() ([]CommPort, error) { err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) if err != nil { log.Fatal("Init error: ", err) } defer ole.CoUninitialize() unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator") defer unknown.Release() wmi, _ := unknown.QueryInterface(ole.IID_IDispatch) defer wmi.Release() serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer") service := serviceRaw.ToIDispatch() defer service.Release() query := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0 and Name like '%(COM%'" queryResult, err2 := oleutil.CallMethod(service, "ExecQuery", query) commPorts := []CommPort{} if err2 != nil { log.Printf("Error from oleutil.CallMethod: ", err2) return nil, err2 } result := queryResult.ToIDispatch() defer result.Release() countVar, _ := oleutil.GetProperty(result, "Count") count := int(countVar.Val) // Should we filter on VID/PID here or later? for i := 0; i < count; i++ { itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) item := itemRaw.ToIDispatch() defer item.Release() displayName, _ := oleutil.GetProperty(item, "Name") fmt.Printf("Port found: %s\n", displayName.ToString()) re := regexp.MustCompile("\\((COM[0-9]+)\\)").FindAllStringSubmatch(displayName.ToString(), 1) var path string = "" if re != nil && len(re[0]) > 1 { path = re[0][1] } fmt.Printf("Path: %v\n", path) deviceId, _ := oleutil.GetProperty(item, "DeviceID") re = regexp.MustCompile("ID_(....)").FindAllStringSubmatch(deviceId.ToString(), 2) var VID, PID uint16 = 0, 0 if re != nil && len(re) == 2 { if len(re[0]) > 1 { val, _ := strconv.ParseUint(re[0][1], 16, 16) VID = uint16(val) } if len(re[1]) > 1 { val, _ := strconv.ParseUint(re[1][1], 16, 16) PID = uint16(val) } fmt.Printf("VID: %v, PID: %v\n", VID, PID) } commPorts = append(commPorts, CommPort{Path: path, VendorId: VID, ProductId: PID, DisplayName: displayName.ToString()}) } return commPorts, err }
func listComPorts() { // init COM ole.CoInitialize(0) defer ole.CoUninitialize() locator, err := oleutil.CreateObject("WbemScripting.SWbemLocator") if err != nil { log.Fatal(err) } defer locator.Release() wmi, err := locator.QueryInterface(ole.IID_IDispatch) if err != nil { log.Fatal(err) } defer wmi.Release() // service is a SWbemServices serviceRaw, err := oleutil.CallMethod(wmi, "ConnectServer") if err != nil { log.Fatal(err) } service := serviceRaw.ToIDispatch() defer service.Release() // result is a SWBemObjectSet resultRaw, err := oleutil.CallMethod(service, "ExecQuery", "SELECT * FROM Win32_PnPEntity WHERE Name LIKE '%(COM%)'") if err != nil { log.Fatal(err) } result := resultRaw.ToIDispatch() defer result.Release() countVar, err := oleutil.GetProperty(result, "Count") if err != nil { log.Fatal(err) } count := int(countVar.Val) var ports Ports re := regexp.MustCompile(`(.*) \(COM(\d+)\)$`) for i := 0; i < count; i++ { // item is a SWbemObject, but really a Win32_Process itemRaw, err := oleutil.CallMethod(result, "ItemIndex", i) if err != nil { continue } item := itemRaw.ToIDispatch() defer item.Release() property, err := oleutil.GetProperty(item, "Name") if err != nil { continue } port := re.FindAllStringSubmatch(property.ToString(), -1) num, _ := strconv.Atoi(port[0][2]) ports = append(ports, Port{num, port[0][1]}) } sort.Sort(ports) digit := getDigit(ports[len(ports)-1].Number) for i := 0; i < len(ports); i++ { fmt.Println("COM" + strconv.Itoa(ports[i].Number) + strings.Repeat(" ", digit-getDigit(ports[i].Number)) + " : " + ports[i].Name) } }
func getListViaWmiPnpEntity() ([]OsSerialPort, os.SyscallError) { //log.Println("Doing getListViaWmiPnpEntity()") // this method panics a lot and i'm not sure why, just catch // the panic and return empty list defer func() { if e := recover(); e != nil { // e is the interface{} typed-value we passed to panic() log.Println("Got panic: ", e) // Prints "Whoops: boom!" } }() var err os.SyscallError //var friendlyName string // init COM, oh yeah ole.CoInitialize(0) defer ole.CoUninitialize() unknown, _ := oleutil.CreateObject("WbemScripting.SWbemLocator") defer unknown.Release() wmi, _ := unknown.QueryInterface(ole.IID_IDispatch) defer wmi.Release() // service is a SWbemServices serviceRaw, _ := oleutil.CallMethod(wmi, "ConnectServer") service := serviceRaw.ToIDispatch() defer service.Release() // result is a SWBemObjectSet //pname := syscall.StringToUTF16("SELECT * FROM Win32_PnPEntity where Name like '%" + "COM35" + "%'") pname := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0 and Name like '%(COM%'" //pname := "SELECT * FROM Win32_PnPEntity WHERE ConfigManagerErrorCode = 0" resultRaw, err2 := oleutil.CallMethod(service, "ExecQuery", pname) //log.Println("Got result from oleutil.CallMethod") if err2 != nil { // we got back an error or empty list log.Printf("Got an error back from oleutil.CallMethod. err:%v", err2) return nil, err } result := resultRaw.ToIDispatch() defer result.Release() countVar, _ := oleutil.GetProperty(result, "Count") count := int(countVar.Val) list := make([]OsSerialPort, count) for i := 0; i < count; i++ { // items we're looping thru look like below and // thus we can query for any of these names /* __GENUS : 2 __CLASS : Win32_PnPEntity __SUPERCLASS : CIM_LogicalDevice __DYNASTY : CIM_ManagedSystemElement __RELPATH : Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14&0&0002" __PROPERTY_COUNT : 24 __DERIVATION : {CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement} __SERVER : JOHN-ATIV __NAMESPACE : root\cimv2 __PATH : \\JOHN-ATIV\root\cimv2:Win32_PnPEntity.DeviceID="USB\\VID_1D50&PID_606D&MI_02\\6&2F09EA14 &0&0002" Availability : Caption : TinyG v2 (Data Channel) (COM12) ClassGuid : {4d36e978-e325-11ce-bfc1-08002be10318} CompatibleID : {USB\Class_02&SubClass_02&Prot_01, USB\Class_02&SubClass_02, USB\Class_02} ConfigManagerErrorCode : 0 ConfigManagerUserConfig : False CreationClassName : Win32_PnPEntity Description : TinyG v2 (Data Channel) DeviceID : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002 ErrorCleared : ErrorDescription : HardwareID : {USB\VID_1D50&PID_606D&REV_0097&MI_02, USB\VID_1D50&PID_606D&MI_02} InstallDate : LastErrorCode : Manufacturer : Synthetos (www.synthetos.com) Name : TinyG v2 (Data Channel) (COM12) PNPDeviceID : USB\VID_1D50&PID_606D&MI_02\6&2F09EA14&0&0002 PowerManagementCapabilities : PowerManagementSupported : Service : usbser Status : OK StatusInfo : SystemCreationClassName : Win32_ComputerSystem SystemName : JOHN-ATIV PSComputerName : JOHN-ATIV */ // item is a SWbemObject, but really a Win32_Process itemRaw, _ := oleutil.CallMethod(result, "ItemIndex", i) item := itemRaw.ToIDispatch() defer item.Release() asString, _ := oleutil.GetProperty(item, "Name") //log.Println(asString.ToString()) // get the com port //if false { s := strings.Split(asString.ToString(), "(COM")[1] s = "COM" + s s = strings.Split(s, ")")[0] list[i].Name = s list[i].FriendlyName = asString.ToString() //} // get the deviceid so we can figure out related ports // it will look similar to // USB\VID_1D50&PID_606D&MI_00\6&2F09EA14&0&0000 deviceIdStr, _ := oleutil.GetProperty(item, "DeviceID") devIdItems := strings.Split(deviceIdStr.ToString(), "&") log.Printf("DeviceId elements:%v", devIdItems) if len(devIdItems) > 3 { list[i].SerialNumber = devIdItems[3] //list[i].IdProduct = strings.Replace(devIdItems[1], "PID_", "", 1) //list[i].IdVendor = strings.Replace(devIdItems[0], "USB\\VID_", "", 1) } else { list[i].SerialNumber = deviceIdStr.ToString() } pidMatch := regexp.MustCompile("PID_(....)").FindAllStringSubmatch(deviceIdStr.ToString(), -1) if len(pidMatch) > 0 { if len(pidMatch[0]) > 1 { list[i].IdProduct = pidMatch[0][1] } } vidMatch := regexp.MustCompile("VID_(....)").FindAllStringSubmatch(deviceIdStr.ToString(), -1) if len(vidMatch) > 0 { if len(vidMatch[0]) > 1 { list[i].IdVendor = vidMatch[0][1] } } manufStr, _ := oleutil.GetProperty(item, "Manufacturer") list[i].Manufacturer = manufStr.ToString() descStr, _ := oleutil.GetProperty(item, "Description") list[i].Product = descStr.ToString() //classStr, _ := oleutil.GetProperty(item, "CreationClassName") //list[i].DeviceClass = classStr.ToString() } for index, element := range list { log.Printf("index:%v, name:%v, friendly:%v ", index, element.Name, element.FriendlyName) log.Printf("pid:%v, vid:%v", element.IdProduct, element.IdVendor) for index2, element2 := range list { if index == index2 { continue } if element.SerialNumber == element2.SerialNumber { log.Printf("Found related element1:%v, element2:%v", element, element2) list[index].RelatedNames = append(list[index].RelatedNames, element2.Name) } } } return list, err }
// loadEntity loads a SWbemObject into a struct pointer. func (c *Client) loadEntity(dst interface{}, src *ole.IDispatch) (errFieldMismatch error) { v := reflect.ValueOf(dst).Elem() for i := 0; i < v.NumField(); i++ { f := v.Field(i) of := f isPtr := f.Kind() == reflect.Ptr if isPtr { ptr := reflect.New(f.Type().Elem()) f.Set(ptr) f = f.Elem() } n := v.Type().Field(i).Name if !f.CanSet() { return &ErrFieldMismatch{ StructType: of.Type(), FieldName: n, Reason: "CanSet() is false", } } prop, err := oleutil.GetProperty(src, n) if err != nil { if !c.AllowMissingFields { errFieldMismatch = &ErrFieldMismatch{ StructType: of.Type(), FieldName: n, Reason: "no such struct field", } } continue } defer prop.Clear() switch val := prop.Value().(type) { case int8, int16, int32, int64, int: v := reflect.ValueOf(val).Int() switch f.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: f.SetInt(v) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: f.SetUint(uint64(v)) default: return &ErrFieldMismatch{ StructType: of.Type(), FieldName: n, Reason: "not an integer class", } } case uint8, uint16, uint32, uint64: v := reflect.ValueOf(val).Uint() switch f.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: f.SetInt(int64(v)) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: f.SetUint(v) default: return &ErrFieldMismatch{ StructType: of.Type(), FieldName: n, Reason: "not an integer class", } } case string: switch f.Kind() { case reflect.String: f.SetString(val) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: iv, err := strconv.ParseInt(val, 10, 64) if err != nil { return err } f.SetInt(iv) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: uv, err := strconv.ParseUint(val, 10, 64) if err != nil { return err } f.SetUint(uv) case reflect.Struct: switch f.Type() { case timeType: if len(val) == 25 { mins, err := strconv.Atoi(val[22:]) if err != nil { return err } val = val[:22] + fmt.Sprintf("%02d%02d", mins/60, mins%60) } t, err := time.Parse("20060102150405.000000-0700", val) if err != nil { return err } f.Set(reflect.ValueOf(t)) } } case bool: switch f.Kind() { case reflect.Bool: f.SetBool(val) default: return &ErrFieldMismatch{ StructType: of.Type(), FieldName: n, Reason: "not a bool", } } default: typeof := reflect.TypeOf(val) if typeof == nil && (isPtr || c.NonePtrZero) { if (isPtr && c.PtrNil) || (!isPtr && c.NonePtrZero) { of.Set(reflect.Zero(of.Type())) } break } return &ErrFieldMismatch{ StructType: of.Type(), FieldName: n, Reason: fmt.Sprintf("unsupported type (%T)", val), } } } return errFieldMismatch }
//get cell pointer. func (sheet Sheet) Cell(r int, c int) (cell Cell, err error) { defer Except("Sheet.Cell", &err) _cell, err := oleutil.GetProperty(sheet.Idisp, "Cells", r, c) cell = Cell{_cell.ToIDispatch()} return }
func (mso *MSO) ActiveWorkBook() (WorkBook, error) { _wb, err := oleutil.GetProperty(mso.IdExcel, "ActiveWorkBook") return WorkBook{_wb.ToIDispatch(), mso}, err }
func (rc *AdodbRows) Next(dest []driver.Value) error { unknown, err := oleutil.GetProperty(rc.rc, "EOF") if err != nil { return io.EOF } if unknown.Val != 0 { return io.EOF } unknown, err = oleutil.GetProperty(rc.rc, "Fields") if err != nil { return err } fields := unknown.ToIDispatch() defer fields.Release() for i := range dest { var varval ole.VARIANT varval.VT = ole.VT_I4 varval.Val = int64(i) val, err := oleutil.CallMethod(fields, "Item", &varval) if err != nil { return err } field := val.ToIDispatch() defer field.Release() typ, err := oleutil.GetProperty(field, "Type") if err != nil { return err } val, err = oleutil.GetProperty(field, "Value") if err != nil { return err } sc, err := oleutil.GetProperty(field, "NumericScale") field.Release() if val.VT == 1 /* VT_NULL */ { dest[i] = nil continue } switch typ.Val { case 0: // ADEMPTY dest[i] = nil case 2: // ADSMALLINT dest[i] = int64(int16(val.Val)) case 3: // ADINTEGER dest[i] = int64(int32(val.Val)) case 4: // ADSINGLE dest[i] = float64(math.Float32frombits(uint32(val.Val))) case 5: // ADDOUBLE dest[i] = math.Float64frombits(uint64(val.Val)) case 6: // ADCURRENCY dest[i] = float64(val.Val) / 10000 case 7: // ADDATE // see http://blogs.msdn.com/b/ericlippert/archive/2003/09/16/eric-s-complete-guide-to-vt-date.aspx d, t := math.Modf(math.Float64frombits(uint64(val.Val))) t = math.Abs(t) dest[i] = time.Date(1899, 12, 30+int(d), 0, 0, int(t*86400), 0, time.Local) case 8: // ADBSTR dest[i] = val.ToString() case 9: // ADIDISPATCH dest[i] = val.ToIDispatch() case 10: // ADERROR // TODO case 11: // ADBOOLEAN dest[i] = val.Val != 0 case 12: // ADVARIANT dest[i] = val case 13: // ADIUNKNOWN dest[i] = val.ToIUnknown() case 14: // ADDECIMAL sub := math.Pow(10, float64(sc.Val)) dest[i] = float64(float64(val.Val) / sub) case 16: // ADTINYINT dest[i] = int8(val.Val) case 17: // ADUNSIGNEDTINYINT dest[i] = uint8(val.Val) case 18: // ADUNSIGNEDSMALLINT dest[i] = uint16(val.Val) case 19: // ADUNSIGNEDINT dest[i] = uint32(val.Val) case 20: // ADBIGINT dest[i] = big.NewInt(val.Val) case 21: // ADUNSIGNEDBIGINT // TODO case 72: // ADGUID dest[i] = val.ToString() case 128: // ADBINARY sa := (*ole.SafeArray)(unsafe.Pointer(uintptr(val.Val))) conv := &ole.SafeArrayConversion{sa} elems, err := conv.TotalElements(0) if err != nil { return err } dest[i] = (*[1 << 30]byte)(unsafe.Pointer(uintptr(sa.Data)))[0:elems] case 129: // ADCHAR dest[i] = val.ToString() //uint8(val.Val) case 130: // ADWCHAR dest[i] = val.ToString() //uint16(val.Val) case 131: // ADNUMERIC sub := math.Pow(10, float64(sc.Val)) dest[i] = float64(float64(val.Val) / sub) case 132: // ADUSERDEFINED dest[i] = uintptr(val.Val) case 133: // ADDBDATE // see http://blogs.msdn.com/b/ericlippert/archive/2003/09/16/eric-s-complete-guide-to-vt-date.aspx d := math.Float64frombits(uint64(val.Val)) dest[i] = time.Date(1899, 12, 30+int(d), 0, 0, 0, 0, time.Local) case 134: // ADDBTIME t := math.Float64frombits(uint64(val.Val)) dest[i] = time.Date(0, 1, 1, 0, 0, int(t*86400), 0, time.Local) case 135: // ADDBTIMESTAMP d, t := math.Modf(math.Float64frombits(uint64(val.Val))) t = math.Abs(t) dest[i] = time.Date(1899, 12, 30+int(d), 0, 0, int(t*86400), 0, time.Local) case 136: // ADCHAPTER dest[i] = val.ToString() case 200: // ADVARCHAR dest[i] = val.ToString() case 201: // ADLONGVARCHAR dest[i] = val.ToString() case 202: // ADVARWCHAR dest[i] = val.ToString() case 203: // ADLONGVARWCHAR dest[i] = val.ToString() case 204: // ADVARBINARY // TODO case 205: // ADLONGVARBINARY sa := (*ole.SafeArray)(unsafe.Pointer(uintptr(val.Val))) conv := &ole.SafeArrayConversion{sa} elems, err := conv.TotalElements(0) if err != nil { return err } dest[i] = (*[1 << 30]byte)(unsafe.Pointer(uintptr(sa.Data)))[0:elems] } } _, err = oleutil.CallMethod(rc.rc, "MoveNext") if err != nil { return err } return nil }