【发布时间】:2020-12-19 20:50:09
【问题描述】:
我已经设法使用 Powershell 脚本读取了一个 OPC XML 项
$wsdl=(Join-path $PSScriptRoot "OpcXmlDa1.00.wsdl")
$global:Proxy = New-WebserviceProxy $wsdl –Namespace X
$global:Options = New-Object X.RequestOptions
$Options.ReturnItemName = $true;
$Options.ReturnItemTime = $true;
$global:ItemList = New-Object X.ReadRequestItemList
$global:RItemList = New-Object X.ReplyItemList
$global:Errors = New-Object X.OPCError
$global:Item = New-Object X.ReadRequestItem
# Read from OPC server
$Proxy.Url = "http://xxx.xx.xx.xxx:xxxx"
$Item.ItemName = "xxx/xxx/xxx"
$ItemList.Items = $Item
$Proxy.Read($Options, $ItemList, [ref]$RItemList, [ref]$Errors)
#Show result
$rTimeStamp = $RItemList.Items[0].Timestamp.ToString('yyyy-MM-dd HH:mm:ss')
$rItemName = $RItemList.Items[0].ItemName
$rValue = $RItemList.Items[0].Value
Write-Host ("{0}: {1}={2}" -f $rTimeStamp, $rItemName, $rValue)
在上面的结果中,我在$RItemList.Items[0] 中看到以下内容
DiagnosticInfo:$null
Value: [UInt32[32]]
Quality: [OPCQuality]
ValueTypeQualifier: $null
ItemPath: ""
ItemName: "xxx/xxx/xxx"
ClientItemHandle: $null
Timestamp: 2020-12 19 01:00:00
TimestampSpecified: $true
ResultID: $null
当我深入研究上面的 Value 时,我发现它按预期读取。到目前为止一切顺利...
现在是我的问题;我无法理解如何通过另一个脚本写入同一个项目。
这是我的尝试
$wsdl=(Join-path $PSScriptRoot "OpcXmlDa1.00.wsdl")
$Global:Proxy = New-WebserviceProxy $wsdl –Namespace X
$Global:Options = New-Object X.RequestOptions
$Options.ReturnItemName = $true;
$Options.ReturnItemTime = $true;
$Options.ReturnDiagnosticInfo = $true;
$Global:writeItemList = New-Object X.WriteRequestItemList
$Global:RItemList = New-Object X.ReplyItemList
$Global:Errors = New-Object X.OPCError
$Global:ItemSessionRequest = New-Object X.ItemValue
$ItemSessionRequest.ValueTypeQualifier = 'xsd:unsignedInt' #<- I believe that this might be the issue?
$ItemSessionRequest.ItemPath = ""
$ItemSessionRequest.ItemName = "xxx/xxx/xxx"
$ItemSessionRequest.Value = @($x;$y;$z) #<- I have what I want to write in $x, $y, $z
# Write to OPC server
$Proxy.Url = "http://xxx.xx.xx.xxx:xxxx"
$ReturnValuesOnReply = $true
$writeItemList.Items = $ItemSessionRequest
$Proxy.Write($Options, $writeItemList, $ReturnValuesOnReply, [ref]$RItemList, [ref]$Errors)
我收到两个错误(我正在通过 VSC 代码运行)。
错误 #1:
DiagnosticInfo : This value to write cannot be NULL
Value :
Quality :
ValueTypeQualifier :
ItemPath :
ItemName : xxx/xxx/SessionRequest
ClientItemHandle :
Timestamp : 1970-01-01 00:59:59
TimestampSpecified : True
ResultID : http://opcfoundation.org/webservices/XMLDA/1.0/:E_BADTYPE
我认为这与我选择的 $ItemSessionRequest.ValueTypeQualifier(我尝试了很多替代方案)有关。
错误 #2:如果我在同一实例中第二次运行脚本,则会出现此错误
Cannot convert argument "Options", with value: "X.RequestOptions", for "Write" to type "X.RequestOptions": "Cannot convert the "X.RequestOptions" value of type "X.RequestOptions" to type "X.Request
Options"."
At C:\bla.bla.ps1:79 char:1
+ $Proxy.Write($Options, $writeItemList, $ReturnValuesOnReply, [ref]$RI ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
我猜这与 $Proxy 变量有关
感谢您的帮助,如果我遗漏了相关内容,我深表歉意,但我已尽力...
【问题讨论】:
-
我认为应该是
xs:unsignedInt。我不知道第二个错误。可能是因为您对某些变量的global:使用不一致,这很不寻常,可能会导致问题。通常你应该只写e。 G。$Proxy = .... -
@zett42 感谢您的提示。但是
xs:unsignedInt给出了同样的错误。关于global:-scope,我同意我的不一致。但是我尝试了多种方式来更改变量的范围并删除脚本末尾的所有变量,以使脚本在同一实例中第二次运行脚本时表现相同。但我仍然得到第二个错误。 -
如何调用脚本?如果您像
. script.ps1一样点源它,那么即使在脚本完成后,所有变量都将保存在内存中。如果您将其称为& script.ps1,那么当脚本结束并启动垃圾收集器时,普通变量将自动从内存中删除。因此,下次脚本运行时,它将从清除状态开始。例外是global:变量,它们无论如何都保留在内存中,所以你不应该使用它们。 -
您也可以尝试在脚本末尾使用
New-Object创建的对象调用dispose()。我不确定这里是否有必要,但它没有伤害。例如。$Global:Proxy.dispose()。这应该在finally块中完成,以确保它即使在发生脚本终止错误时也能运行。 -
再次感谢@zett42。我已经通过
. script.ps1、& script.ps1启动了脚本,并在 Visual Studio Code 中以调试模式运行它。所有方法都给出相同的第二个错误。我还尝试了您的提示,即在脚本末尾调用dispose()而不消除错误(我也尝试过Get-Variable -Exclude PWD,*Preference | Remove-Variable -EA 0)...
标签: powershell wsdl opc