在Go中使用OLE会导致”标签无效”错误。

huangapple go评论85阅读模式
英文:

Utilizing OLE in Go results in "The tag is invalid" error

问题

我正在尝试在Go语言中使用OLE来设置Windows 10上的默认音频输出源。我使用了两个第三方包来完成这个任务:

我遇到的问题是,函数pcv.SetDefaltEndpoint()没有设置默认的输出源,而是返回一个简单的错误消息,内容为The tag is invalid

我使用了这个包的源代码(用C#编写)来确认我提供的GUID和设备ID是正确的,但是我仍然没有成功。

https://github.com/sirWest/AudioSwitch

非常感谢您的帮助。谢谢大家抽出时间来帮助我。

编辑:我刚刚意识到我错误地使用了syscall.SyscallN。似乎旧的用法是提供参数的数量,但是syscallN不需要这个。在纠正了这个错误之后,我现在得到了这个错误:A null reference pointer was passed to the stub.尽管所有的变量都不是空指针。

英文:

I am attempting to utilize OLE in go to set the default audio output source on Windows 10. I am using 2 third-party packages to accomplish this:

The problem that I am having is that the function pcv.SetDefaltEndpoint() is not setting the default output source but is instead returning an error that simply says The tag is invalid.

package main

import (
	"fmt"
	"syscall"
	"unsafe"

	"github.com/go-ole/go-ole"
	"github.com/moutend/go-wca/pkg/wca"
)

type IPolicyConfig struct {
	ole.IUnknown
}

type IPolicyConfigVtbl struct {
	ole.IUnknownVtbl
	GetDeviceFormat       uintptr
	ResetDeviceFormat     uintptr
	SetDeviceFormat       uintptr
	GetProcessingPeriod   uintptr
	SetProcessingPeriod   uintptr
	GetShareMode          uintptr
	SetShareMode          uintptr
	GetPropertyValue      uintptr
	SetPropertyValue      uintptr
	SetDefaultEndpoint    uintptr
	SetEndpointVisibility uintptr
}

func (v *IPolicyConfig) VTable() *IPolicyConfigVtbl {
	return (*IPolicyConfigVtbl)(unsafe.Pointer(v.RawVTable))
}

func (v *IPolicyConfig) SetDefaultEndpoint(deviceID string, eRole wca.ERole) (err error) {
	err = pcvSetDefaultEndpoint(v, deviceID, eRole)
	return
}

func pcvSetDefaultEndpoint(pcv *IPolicyConfig, deviceID string, eRole wca.ERole) (err error) {
	var ptr *uint16
	if ptr, err = syscall.UTF16PtrFromString(deviceID); err != nil {
		return
	}

	hr, _, _ := syscall.SyscallN(
		pcv.VTable().SetDefaultEndpoint,
		3,
		uintptr(unsafe.Pointer(pcv)),
		uintptr(unsafe.Pointer(ptr)),
		uintptr(uint32(eRole)))
	if hr != 0 {
		err = ole.NewError(hr)
	}
	return
}

func main() {
	if err := ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED); err != nil {
		return
	}
	defer ole.CoUninitialize()

	CPolicyConfigClientUID := ole.NewGUID("870AF99C-171D-4F9E-AF0D-E63DF40C2BC9")
	IPolicyConfigUID := ole.NewGUID("F8679F50-850A-41CF-9C72-430F290290C8")

	var pcv *IPolicyConfig
	if err := wca.CoCreateInstance(CPolicyConfigClientUID, 0, wca.CLSCTX_ALL, IPolicyConfigUID, &pcv); err != nil {
		return
	}
	defer pcv.Release()

	fmt.Println(pcv.SetDefaultEndpoint("{0.0.0.00000000}.{81d9ff45-7f2a-4397-9885-0275cb01c816}", wca.EMultimedia))
}

I used the source code of this package (in C#) to confirm that the GUIDs and Device ID I'm supplying are correct but I'm still not having any luck.

https://github.com/sirWest/AudioSwitch

Any help would be greatly appreciated. Thank you all for your time.

EDIT: I just now realized that I was using syscall.SyscallN incorrectly. It appears the old way of using it was to supply the number of arguments, but syscallN does not need this. After correcting this, I'm now getting this error: A null reference pointer was passed to the stub. despite all the variables being supplied to it are not null

答案1

得分: 1

我终于弄清楚了!在我的结构体中,第一个uintptr的单词是GetDeviceFormat而不是GetMixFormat。我希望我的痛苦和困扰能帮助到未来的某个人,即使是在5年后。

英文:

I finally figured it out! For the first uintptr in my struct I had the word GetDeviceFormat not GetMixFormat. I hope my pain and suffering helps somebody, even if it's 5 years in the future.

huangapple
  • 本文由 发表于 2023年3月10日 02:58:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/75688949.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定