TCP client reconnection logic running on 30 machines
catch (Exception)
{
  Reconnect();
}



The same pattern can be found in almost every method. Are you not interested in what happened? No logging or anything? Just ignore the exception?




_pingTimer = new Timer { Interval = 2000 };
Thread.Sleep(500);



Hardcoded numbers? No settings? What if this won't work and you have to tune it? You'll have to update all instances!




Enum.TryParse(messageParts[0], out MessageType messagetype);



Why isn't this inside an if?


if (messagetype == MessageType.UpdateContentType)



This is the next line following the TryParse but this can go sideways if the UpdateContentType is the first value of the enum it might be returned as a default value and the flow will enter the if even if the massage part wasn't in the correct format.




private void TcpClientOnDataReceived(object sender, Message message)



You have try/catches for everything but this method. If something goes wrong here the application will crash.




  60 instances of this program are supposed to run on 30 machines, meaning there are 2 instances of it running on each machine. It is used to keep all the client instances (running this code) connected to the controller that gives them updates when needed.


This sounds like too much. Why can't the client check for updates by itself? 


  Once the software is deployed, I will most likely not be able to make any changes anymore.


If you are not able to update it later then you should start writing all kinds of unit and integration tests to make sure it's bullet-proof but even then there will still be a bug somewhere... Not being able to deploy new versions is a terrible plan.