OPC UA写入原始数据:C#调用Open方法失败求助(西门子数控场景)
Hey there! Let's break down why you're hitting that frustrating "Bad invalid argument" error when trying to open the file after using CopyFileToServer. The root issue is exactly what you suspected: you're not correctly getting the NodeId of the file you just created. Here's how to fix it:
Key Problem: You're Ignoring the CopyFileToServer Return Value
When you successfully call CopyFileToServer (a method of the FileDirectoryType), it returns the NodeId of the newly created FileType node for your file. Right now, you're storing that return value in var a but not using it—this is the NodeId you need to target for your Open method call.
Step-by-Step Fix
Capture and Convert the
CopyFileToServerResult
Thesession.Callmethod returns anIList<object>where the first element is the NodeId of the created file. You'll need to cast this to aNodeId(or parse it if it's returned as a string, depending on your server's implementation).Replace the Hardcoded File NodeId
Ditch the placeholderNodeId nodeFile = new NodeId("file to open");and use the valid NodeId you just retrieved from the copy operation.
Corrected Code Example
Here's your modified code with critical fixes highlighted:
public void SendFile(Opc.Ua.Client.Session session) { try { if (session != null) { // 1. Grant user access (unchanged logic) NodeId node0 = new NodeId("ns=2;s=/Methods"); NodeId node1 = new NodeId("ns=2;s=/Methods/GiveUserAccess"); object[] argument0 = new object[2]; argument0[0] = "USER"; argument0[1] = "SinuWriteAll"; session.Call(node0, node1, argument0); // 2. Copy file to server and capture the returned file NodeId NodeId node = new NodeId("ns=2;s=/Methods"); NodeId method = new NodeId("ns=2;s=/Methods/CopyFileToServer"); object[] argument = new object[3]; // Note: Replace this placeholder with your actual file byte data later byte[] data = File.ReadAllBytes("path/to/your/sendFile.mpf"); argument[0] = "Sinumerik/FileSystem/Part Program/sendFile.mpf"; argument[1] = data; argument[2] = true; // Get and validate the copy operation result var callResult = session.Call(node, method, argument); if (callResult == null || callResult.Count == 0) { throw new Exception("CopyFileToServer failed to return a valid file NodeId."); } // Convert result to NodeId (handle both direct NodeId and string cases) NodeId nodeFile; if (callResult[0] is NodeId resultNodeId) { nodeFile = resultNodeId; } else if (callResult[0] is string nodeIdString) { nodeFile = NodeId.Parse(nodeIdString); } else { throw new Exception($"Unexpected return type from CopyFileToServer: {callResult[0].GetType()}"); } // 3. Call Open on the valid file NodeId NodeId methodOpen = new NodeId("ns=0;i=11580"); // Standard Open method for FileType object[] argument1 = new object[1]; argument1[0] = OpenFileMode.Write; var hndl = session.Call(nodeFile, methodOpen, argument1); // Next steps: Use the handle to write remaining data, then call Close } } catch (Exception ex) { // Don't swallow exceptions! Log full details for debugging Console.WriteLine($"Error details: {ex.ToString()}"); throw; // Re-throw to let the caller handle the error appropriately } }
Additional Tips
- Stop Swallowing Exceptions: Your original code catches exceptions but does nothing with them—logging
ex.ToString()will give you stack traces and context that make debugging way easier. - Use Actual File Data: I replaced the 1-byte placeholder with
File.ReadAllBytesso you can pass your real.mpffile content. - Siemens Server Quirks: Some Siemens OPC UA servers return NodeIds as strings instead of direct objects, which is why the code handles both casting scenarios.
内容的提问来源于stack exchange,提问作者Tarma

