File system
Browse the controller file system, download and upload files, create, copy, rename and delete files and directories.
robot.Rws.File gives access to the file system of the controller: browse it, download and upload files, and create, rename, copy or delete files and directories. Nothing has to be shared or mounted on the PC.
Paths are the ones used on the controller. The environment variables of the controller are accepted where a path is expected, $home and $temp for example, and they behave as directories. robot.Rws.Controller.GetEnvironmentVariable gives the real path behind such a name.
Browse the file system
ListDirectory returns a DirectoryListing with the files, the subdirectories and, at the root, the storage devices of the controller. The complete content is always returned, however many entries the directory holds.
// The root lists the storage devices of the controllerDirectoryListing root = robot.Rws.File.ListDirectory("/");foreach (DeviceItem device in root.Devices){Console.WriteLine($"{device.Name} ({device.DeviceType}) {device.FreeSpace}/{device.TotalSpace} bytes");}// A directory lists its files and its subdirectoriesDirectoryListing listing = robot.Rws.File.ListDirectory("$home");Console.WriteLine($"{listing.DirectoryCount} directories, {listing.FileCount} files");foreach (DirectoryItem directory in listing.Directories){Console.WriteLine($"[DIR] {directory.Name}");}foreach (FileItem file in listing.Files){Console.WriteLine($"{file.Name} {file.Size} bytes, modified {file.ModificationDate}");}
Pass "/" or null to list the root. The root is where the storage devices are, with their free and total space. A DeviceItem has a DeviceType: Fixed for an internal disk, Removable for a USB key, RamDisk, Remote for a network storage, Unknown otherwise.
FileCount, DirectoryCount, DeviceCount and TotalCount are computed by the SDK, they save a null check on the three arrays.
One class per kind of item
FileItem, DirectoryItem and DeviceItem all derive from FileSystemItem, which carries the name and the dates. There is no flag saying what an item is, the type itself says it.
// The three arrays hold subclasses of the same base classList<FileSystemItem> items = new List<FileSystemItem>();items.AddRange(listing.Directories);items.AddRange(listing.Files);items.AddRange(listing.Devices);foreach (FileSystemItem item in items){// Name, CreationDate and ModificationDate come from the base classConsole.Write($"{item.Name} {item.ModificationDate} ");// What the item really is, is found with a type test, not with a flagif (item is FileItem file){Console.WriteLine($"file of {file.Size} bytes");}else if (item is DirectoryItem directory){Console.WriteLine($"directory, read only: {directory.IsReadOnly}");}else if (item is DeviceItem device){Console.WriteLine($"device of type {device.DeviceType}, {device.FreeSpace} bytes free");}}
CreationDate and ModificationDate are nullable, the controller does not always report them. Size is in bytes and only exists on a file.
Download a file
Four methods read a file, they differ only by what you get back.
| Method | Returns |
|---|---|
GetFileAsText(path, encoding) | string, UTF-8 when no encoding is given |
GetFileAsBytes(path) | byte[] |
GetFileToDestination(path, localPath) | Nothing, the file is written on the PC |
GetFileAsReadonlyStream(path) | A readable Stream |
// A text file, UTF-8 by defaultstring text = robot.Rws.File.GetFileAsText("$home/notes.txt");// Another encoding when the file is not UTF-8string latin = robot.Rws.File.GetFileAsText("$home/notes.txt", Encoding.GetEncoding("iso-8859-1"));// A binary filebyte[] bytes = robot.Rws.File.GetFileAsBytes("$home/backup.zip");// Straight to a file of the PCrobot.Rws.File.GetFileToDestination("$home/backup.zip", @"C:\temp\backup.zip");// As a stream, to copy the content without keeping a second copy of itusing (Stream source = robot.Rws.File.GetFileAsReadonlyStream("$home/backup.zip"))using (FileStream destination = System.IO.File.Create(@"C:\temp\backup.zip")){source.CopyTo(destination);}
Use GetFileAsText for a RAPID module, a configuration file or a log. Use the bytes or the stream for a backup archive or any binary content. The synchronous GetFileAsReadonlyStream buffers the whole content in memory first, for compatibility with .NET Framework 3.5 and 4.0. GetFileAsReadonlyStreamAsync reads from the network as you read the stream, which is the one to use for a large file.
Upload a file
The four upload methods mirror the downloads. An existing file is replaced.
// From a string, UTF-8 by defaultrobot.Rws.File.UploadFileFromText("$home/notes.txt", "Written by the SDK");// From raw bytesrobot.Rws.File.UploadFileFromBytes("$home/data.bin", new byte[] { 1, 2, 3, 4 });// From a file of the PCrobot.Rws.File.UploadFileFromPath("$home/MyModule.mod", @"C:\temp\MyModule.mod");// From a stream, for a large fileusing (FileStream source = System.IO.File.OpenRead(@"C:\temp\MyModule.mod")){robot.Rws.File.UploadFileFromStream("$home/MyModule.mod", source);}
UploadFileFromText writes UTF-8 by default, pass an Encoding for another one. UploadFileFromStream sends the content as it reads it, so a large file does not have to be loaded in memory.
Create the destination directory first with CreateDirectory when it does not exist yet.
Create, rename, copy and delete
// Directories. The new name can be nested, the missing levels are created.robot.Rws.File.CreateDirectory("$home", "MyApp/Logs");robot.Rws.File.RenameDirectory("$home/MyApp/Logs", "Archive");robot.Rws.File.CopyDirectory("$home/MyApp/Archive", "Archive2", true);robot.Rws.File.DeleteDirectory("$home/MyApp/Archive2");// Files. The third argument of the copy overwrites an existing target.robot.Rws.File.RenameFile("$home/notes.txt", "notes-old.txt");robot.Rws.File.CopyFile("$home/notes-old.txt", "notes-backup.txt", true);robot.Rws.File.DeleteFile("$home/notes-old.txt");
A few points to know:
CreateDirectorytakes the parent directory and the new name. The name can be nested, and the missing levels are created.- The new name of a rename or a copy is relative to the directory the item is in. An absolute path on the controller is also accepted.
- The copy methods take an
overwriteargument. Withfalse, the controller refuses to replace an existing target. DeleteDirectorydeletes the directory and its content. There is no recycle bin on the controller, a deleted file is gone.
The controller protects part of its file system. A write in a read only location fails with an RwsException, and IsReadOnly on the item tells you before you try. The user account also needs the matching UAS grant.
Around the file system
Other services write files on the controller and leave them for this one to read:
- Controller writes a backup in a folder of the controller. Browse that folder and download its files, as shown in Backup & restore a controller.
- Event log writes the whole log to one file with
SaveInSystemDumpFormat. - RAPID modules loads a module from a path on the controller, so a module written from the PC is uploaded first and loaded afterwards.
Nothing here needs the mastership, the file system is not one of its domains. Loading into RAPID what you uploaded does need it.
API reference
Methods of FileService :// Copies a directory (synchronous)void CopyDirectory(string path, string newName, bool overwrite);// Copies a file (synchronous)void CopyFile(string path, string newName, bool overwrite);// Creates a new directory (synchronous) The newName parameter can contain nested directory structure (e.g. "parentdir/subdir") which will create both directories if they don't exist.void CreateDirectory(string path, string newName);// Deletes a directory and all its subdirectories and files (synchronous)void DeleteDirectory(string path);// Deletes a file (synchronous)void DeleteFile(string path);// Gets file content as raw bytes (synchronous)byte[] GetFileAsBytes(string path);// Gets file content as a read-only stream (synchronous) For sync: Returns a read-only MemoryStream (buffered for .NET 3.5/4.0 compatibility) For true HTTP streaming with large files, use GetFileAsReadonlyStreamAsync() insteadStream GetFileAsReadonlyStream(string path);// Gets file content as text (synchronous)string GetFileAsText(string path, Encoding encoding = null);// Downloads a file to a local path (synchronous)void GetFileToDestination(string path, string localPath);// Lists contents of a directory resource (synchronous) Environment variables (e.g. $home, $temp) and devices are treated as directories. When listing the root path ("/", null, or "\\"), the response includes available devices in DirectoryListing.Devices. The complete content is always returned, however many entries the directory holds.DirectoryListing ListDirectory(string path);// Renames a directory (synchronous)void RenameDirectory(string path, string newName);// Renames a file (synchronous)void RenameFile(string path, string newName);// Uploads a file from raw bytes (synchronous)void UploadFileFromBytes(string path, byte[] content, string contentType = null);// Uploads a local file to the controller (synchronous)void UploadFileFromPath(string path, string localPath, string contentType = null);// Uploads a file from a stream (synchronous)void UploadFileFromStream(string path, Stream contentStream, string contentType = null);// Uploads a file from text (synchronous)void UploadFileFromText(string path, string content, Encoding encoding = null);
Every method also exists in an asynchronous version, with the same name followed by Async and an optional CancellationToken.
public class DirectoryListing {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.DirectoryListing" data-throw-if-not-resolved="false"></xref> classpublic DirectoryListing(string path)// Number of devices in this listingpublic int DeviceCount { get; }// Devices available in this listing (typically only present at root "/")public DeviceItem[] Devices { get; set; }// Subdirectories contained in this directorypublic DirectoryItem[] Directories { get; set; }// Number of subdirectories in this listingpublic int DirectoryCount { get; }// Number of files in this listingpublic int FileCount { get; }// Files contained in this directorypublic FileItem[] Files { get; set; }// Path that was listedpublic string Path { get; }// Returns a string representation of this directory listingpublic override string ToString()// Total number of items (files + directories + devices)public int TotalCount { get; }}
public abstract class FileSystemItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.FileSystemItem" data-throw-if-not-resolved="false"></xref> classprotected FileSystemItem()// Creation date of the resource, if availablepublic DateTime? CreationDate { get; set; }// Last modification date of the resource, if availablepublic DateTime? ModificationDate { get; set; }// Name of the item (file name, directory name, or device name such as "C:")public string Name { get; set; }// Returns the name of the itempublic override string ToString()}
public class FileItem : FileSystemItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.FileItem" data-throw-if-not-resolved="false"></xref> classpublic FileItem()// Indicates if the file is read-onlypublic bool IsReadOnly { get; set; }// File size in bytespublic long Size { get; set; }// Returns a string representation of this file entrypublic override string ToString()}
public class DirectoryItem : FileSystemItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.DirectoryItem" data-throw-if-not-resolved="false"></xref> classpublic DirectoryItem()// Indicates if the directory is read-onlypublic bool IsReadOnly { get; set; }// Returns a string representation of this directory entrypublic override string ToString()}
public class DeviceItem : FileSystemItem {// Initializes a new instance of the <xref href="UnderAutomation.ABB.Rws.Data.DeviceItem" data-throw-if-not-resolved="false"></xref> classpublic DeviceItem()// Type of device (Fixed, Removable, RamDisk, Remote)public DeviceType DeviceType { get; set; }// Free storage space in bytespublic long FreeSpace { get; set; }// Indicates if the device is enabledpublic bool IsEnabled { get; set; }// Indicates if the device is read-onlypublic bool IsReadOnly { get; set; }// Returns a string representation of this device entrypublic override string ToString()// Total storage space in bytespublic long TotalSpace { get; set; }}
public enum DeviceType {// Fixed storage device (hard drive)Fixed = 0// RAM diskRamDisk = 2// Remote or network storageRemote = 3// Removable storage device (USB, SD card, etc.)Removable = 1// Unknown device typeUnknown = 4}