Read/Write string types

ADS Server usually support strings in 2 flavors. The Default (ANSI) and the Unicode encoding (STRING vs. WSTRING) The ANSI encoding reserves 1 byte per character. Unicode reserves 2.

The strings are of fixed size and therefore the length of the the reserved space within the process image is important.

HowTo Read/Write string values

Reading writing ANSI Streams:

Read/Write ANSI Strings (async)

CancellationToken cancel = CancellationToken.None;

using (AdsClient client = new AdsClient())
{
    client.Connect(AmsNetId.Local, 851); // Connect to local port 851 (PLC)

    ResultHandle resultHandle = await client.CreateVariableHandleAsync("MAIN.string",cancel); // Symbol "string" in MAIN defined as string

    if (resultHandle.Succeeded)
    {
    try
    {
        // Read ANSI String string[80]
        int byteSize = 81; // Size of 80 ANSI chars + /0 (STRING[80])
        PrimitiveTypeMarshaler converter = new PrimitiveTypeMarshaler(StringMarshaler.DefaultEncoding);
        byte[] buffer = new byte[byteSize];

        ResultRead resultRead = await client.ReadAsync(resultHandle.Handle, buffer.AsMemory(), cancel);

        if (resultRead.Succeeded)
        {
        string value = null;
        converter.Unmarshal<string>(buffer.AsSpan(), out value);

        byte[] writeBuffer = new byte[byteSize];
        // Write ANSI String string[80]
        value = "Changed";
        converter.Marshal(value, writeBuffer);
        ResultWrite resultWrite = await client.WriteAsync(resultHandle.Handle, writeBuffer, cancel);
        }
    }
    finally
    {
        ResultAds r1 = await client.DeleteVariableHandleAsync(resultHandle.Handle, cancel);
    }
    }
}

Read/Write ANSI Strings (sync)

using (AdsClient client = new AdsClient())
{
    client.Connect(AmsNetId.Local, 851); // Connect to local port 851 (PLC)
    uint handle = client.CreateVariableHandle("MAIN.string"); // Symbol "string" in MAIN defined as string

    try
    {
    // Read ANSI String string[80]
    int byteSize = 81; // Size of 80 ANSI chars + /0 (STRING[80])
    PrimitiveTypeMarshaler converter = new PrimitiveTypeMarshaler(StringMarshaler.DefaultEncoding);
    byte[] buffer = new byte[byteSize];

    int readBytes = client.Read(handle, buffer.AsMemory());

    string value = null;
    converter.Unmarshal<string>(buffer.AsSpan(), out value);

    // Write ANSI String string[80]
    byte[] writeBuffer = new byte[byteSize];
    value = "Changed";
    converter.Marshal(value, writeBuffer);
    client.Write(handle, writeBuffer);
    }
    finally
    {
    client.DeleteVariableHandle(handle);
    }
}

Reading writing UNICODE Streams:

Read/Write Unicode Strings (async)

CancellationToken cancel = CancellationToken.None;

using (AdsClient client = new AdsClient())
{
    client.Connect(AmsNetId.Local, 851); // Connect to local port 851 (PLC)
    ResultHandle resultHandle = await client.CreateVariableHandleAsync("MAIN.wstring",cancel); // Symbol "wstring" defined in MAIN as WSTRING

    if (resultHandle.Succeeded)
    {
    try
    {
        // Read UNICODE String wstring[80]
        PrimitiveTypeMarshaler converter = new PrimitiveTypeMarshaler(Encoding.Unicode);
        int byteSize = converter.MarshalSize(80); // Size of 80 UNICODE chars + /0 (WSTRING[80]) (162)
        byte[] readBuffer = new byte[byteSize];

        ResultRead resultRead = await client.ReadAsync(resultHandle.Handle, readBuffer, cancel);

        if (resultRead.Succeeded)
        {
        string value = null;
        converter.Unmarshal(readBuffer.AsSpan(), out value);

        // Write Unicode String string[80]
        value = "Changed";
        byte[] writeBuffer = new byte[byteSize];
        converter.Marshal(value, writeBuffer.AsSpan());

        ResultWrite resultWrite = await client.WriteAsync(resultHandle.Handle, writeBuffer.AsMemory(), cancel);
        }
    }
    finally
    {
        ResultAds r1 = await client.DeleteVariableHandleAsync(resultHandle.Handle, cancel);
    }
    }
}

Read/Write Unicode Strings (sync)

using (AdsClient client = new AdsClient())
{
    client.Connect(AmsNetId.Local, 851); // Connect to local port 851 (PLC)
    uint handle = client.CreateVariableHandle("MAIN.wstring"); // Symbol "wstring" defined in MAIN as WSTRING

    try
    {
    // Read UNICODE String wstring[80]

    PrimitiveTypeMarshaler converter = new PrimitiveTypeMarshaler(Encoding.Unicode);
    int byteSize = converter.MarshalSize(80); // Size of 80 UNICODE chars + /0 (WSTRING[80]) (162)
    byte[] readBuffer = new byte[byteSize];

    int readBytes = client.Read(handle, readBuffer);

    string value = null;
    converter.Unmarshal(readBuffer.AsSpan(), out value);

    // Write Unicode String string[80]
    value = "Changed";
    byte[] writeBuffer = new byte[byteSize];
    converter.Marshal(value, writeBuffer.AsSpan());

    client.Write(handle, writeBuffer.AsMemory());
    }
    finally
    {
    client.DeleteVariableHandle(handle);
    }
}

Reading writing strings with ReadAny/WriteAny group of methods:

Read/Write Anystring (async)

CancellationToken cancel = CancellationToken.None;

using (AdsClient client = new AdsClient())
{
    client.Connect(AmsNetId.Local, 851); // Connect to local port 851 (PLC)

    ResultHandle resultHandleStr = await client.CreateVariableHandleAsync("MAIN.string",cancel); // Symbol "string" defined in MAIN as STRING
    ResultHandle resultHandleWStr = await client.CreateVariableHandleAsync("MAIN.wstring",cancel); // Symbol "string" defined in MAIN as WSTRING

    if (resultHandleStr.Succeeded && resultHandleWStr.Succeeded)
    {
    try
    {
        ResultAnyValue resultReadStr = await client.ReadAnyStringAsync(resultHandleStr.Handle, 80, StringMarshaler.DefaultEncoding, cancel);
        ResultAnyValue resultReadWStr = await client.ReadAnyStringAsync(resultHandleWStr.Handle, 80, Encoding.Unicode, cancel);

        string changedValue = "Changed";

        // Attention, take care that the memory of the string in the process image is not exceeded!
        ResultWrite resultWriteStr = await client.WriteAnyStringAsync(resultHandleStr.Handle, changedValue, 80, StringMarshaler.DefaultEncoding, cancel);
        ResultWrite resultWriteWStr = await client.WriteAnyStringAsync(resultHandleWStr.Handle, changedValue, 80, Encoding.Unicode, cancel);
    }
    finally
    {
        ResultAds r1 = await client.DeleteVariableHandleAsync(resultHandleStr.Handle, cancel);
        ResultAds r2 = await client.DeleteVariableHandleAsync(resultHandleWStr.Handle, cancel);
    }
    }
}

Read/Write Anystring (sync)

using (AdsClient client = new AdsClient())
{
    client.Connect(AmsNetId.Local, 851); // Connect to local port 851 (PLC)

    uint stringHandle = client.CreateVariableHandle("MAIN.string"); // Symbol "string" defined in MAIN as STRING
    uint wStringHandle = client.CreateVariableHandle("MAIN.wstring"); // Symbol "string" defined in MAIN as WSTRING

    try
    {
    string str = client.ReadAnyString(stringHandle, 80, StringMarshaler.DefaultEncoding);
    string wStr = client.ReadAnyString(wStringHandle, 80, Encoding.Unicode);

    string changedValue = "Changed";

    // Attention, take care that the memory of the string in the process image is not exceeded!
    client.WriteAnyString(stringHandle, changedValue, 80, StringMarshaler.DefaultEncoding);
    client.WriteAnyString(wStringHandle, changedValue, 80, Encoding.Unicode);
    }
    finally
    {
    client.DeleteVariableHandle(stringHandle);
    client.DeleteVariableHandle(wStringHandle);
    }
}