Tworzenie oprogramowania dla usługi Azure Files przy użyciu platformy .NET
Poznaj podstawy tworzenia aplikacji platformy .NET, które używają usługi Azure Files do przechowywania danych. W tym artykule pokazano, jak utworzyć prostą aplikację konsolową, aby wykonać następujące czynności za pomocą platformy .NET i usługi Azure Files:
- Pobierz zawartość pliku.
- Ustaw maksymalny rozmiar lub limit przydziału dla udziału plików.
- Utwórz sygnaturę dostępu współdzielonego (SAS) dla pliku.
- Skopiowanie pliku do innego pliku w tym samym koncie magazynu.
- Skopiowanie pliku do obiektu blob w tym samym koncie magazynu.
- Utwórz migawkę udziału plików.
- Przywracanie pliku z migawki udziału.
- Rozwiązywanie problemów przy użyciu metryk usługi Azure Storage.
Aby dowiedzieć się więcej o usłudze Azure Files, zobacz Co to jest usługa Azure Files?
Napiwek
Zapoznaj się z repozytorium przykładów kodu usługi Azure Storage
Nasza lista przykładów usługi Azure Storage zawiera łatwe w użyciu kompleksowe przykłady kodu usługi Azure Storage, które można pobierać i uruchamiać.
Dotyczy
Typ udziału plików | SMB | NFS |
---|---|---|
Udziały plików w warstwie Standardowa (GPv2), LRS/ZRS | ||
Udziały plików w warstwie Standardowa (GPv2), GRS/GZRS | ||
Udziały plików w warstwie Premium (FileStorage), LRS/ZRS |
Opis interfejsów API platformy .NET
Usługa Azure Files oferuje dwa obszerne podejścia do aplikacji klienckich: blok komunikatów serwera (SMB) i interfejs REST. W ramach platformy .NET System.IO
interfejsy API i Azure.Storage.Files.Shares
tworzą abstrakcję tych podejść.
interfejs API | Kiedy używać | Uwagi |
---|---|---|
System.IO | Aplikacja:
|
We/Wy plików zaimplementowanych za pomocą usługi Azure Files za pośrednictwem protokołu SMB jest zazwyczaj taka sama jak we/wy z dowolnym sieciowym udziałem plików lub lokalnym urządzeniem magazynu. Aby zapoznać się z wprowadzeniem do wielu funkcji na platformie .NET, w tym we/wy plików, zobacz samouczek aplikacja konsolowa. |
Azure.Storage.Files.Shares | Aplikacja:
|
W tym artykule przedstawiono użycie funkcji Azure.Storage.Files.Shares we/wy plików przy użyciu interfejsu REST zamiast protokołu SMB i zarządzania udziałem plików. |
Tworzenie aplikacji konsolowej i uzyskiwanie zestawu
Bibliotekę klienta usługi Azure Files można używać w dowolnym typie aplikacji .NET. Te aplikacje obejmują chmurę platformy Azure, internet, komputery i aplikacje mobilne. W tym przewodniku utworzymy aplikację konsolową dla uproszczenia.
W programie Visual Studio utwórz nową aplikację konsoli dla systemu Windows. Poniższe kroki pokazują, jak utworzyć aplikację konsolową w programie Visual Studio 2019. Procedura jest podobna w innych wersjach programu Visual Studio.
- Uruchom program Visual Studio i wybierz pozycję Utwórz nowy projekt.
- W obszarze Utwórz nowy projekt wybierz pozycję Aplikacja konsolowa (.NET Framework) dla języka C#, a następnie wybierz pozycję Dalej.
- W obszarze Konfigurowanie nowego projektu wprowadź nazwę aplikacji, a następnie wybierz pozycję Utwórz.
Dodaj wszystkie przykłady kodu w tym artykule do Program
klasy w pliku Program.cs .
Użycie pakietu NuGet w celu zainstalowania wymaganych pakietów
Zapoznaj się z tymi pakietami w projekcie:
- Podstawowa biblioteka platformy Azure dla platformy .NET: ten pakiet jest implementacją potoku klienta platformy Azure.
- Biblioteka klienta obiektów blob usługi Azure Storage dla platformy .NET: ten pakiet zapewnia programowy dostęp do zasobów obiektów blob na koncie magazynu.
- Biblioteka klienta usługi Azure Storage Files dla platformy .NET: ten pakiet zapewnia programowy dostęp do zasobów plików na koncie magazynu.
- Biblioteka programu System Configuration Manager dla platformy .NET: ten pakiet zawiera klasę przechowującąc i pobierając wartości w pliku konfiguracji.
Możesz użyć narzędzia NuGet, aby uzyskać pakiety. Wykonaj te kroki:
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy projekt i wybierz polecenie Zarządzaj pakietami NuGet.
W Menedżer pakietów NuGet wybierz pozycję Przeglądaj. Następnie wyszukaj i wybierz pozycję Azure.Core, a następnie wybierz pozycję Zainstaluj.
Ten krok powoduje zainstalowanie pakietu i jego zależności.
Wyszukaj i zainstaluj następujące pakiety:
- Azure.Storage.Blobs
- Azure.Storage.Files.Shares
- System.Configuration.ConfigurationManager
Zapisywanie poświadczeń konta magazynu w pliku App.config
Następnie zapisz swoje poświadczenia w pliku App.config projektu. W Eksplorator rozwiązań kliknij App.config
dwukrotnie i edytuj plik, aby był podobny do poniższego przykładu.
Zastąp myaccount
ciąg nazwą konta magazynu i mykey
kluczem konta magazynu.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="StorageConnectionString"
value="DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey;EndpointSuffix=core.windows.net" />
<add key="StorageAccountName" value="myaccount" />
<add key="StorageAccountKey" value="mykey" />
</appSettings>
</configuration>
Uwaga
Emulator magazynu Azurite nie obsługuje obecnie usługi Azure Files. Aby móc pracować z usługą Azure Files, parametry połączenia musi być przeznaczone konto usługi Azure Storage w chmurze.
Dodawanie dyrektyw using
W Eksplorator rozwiązań otwórz plik Program.cs i dodaj następujące dyrektywy using na początku pliku.
using System;
using System.Configuration;
using System.IO;
using System.Threading.Tasks;
using Azure;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;
using Azure.Storage.Sas;
Programowy dostęp do udziału plików
W pliku Program.cs dodaj następujący kod, aby programowo uzyskać dostęp do udziału plików.
Poniższa metoda tworzy udział plików, jeśli jeszcze nie istnieje. Metoda rozpoczyna się od utworzenia obiektu ShareClient na podstawie parametry połączenia. Następnie przykład próbuje pobrać utworzony wcześniej plik. Wywołaj tę metodę z Main()
klasy .
//-------------------------------------------------
// Create a file share
//-------------------------------------------------
public async Task CreateShareAsync(string shareName)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instantiate a ShareClient which will be used to create and manipulate the file share
ShareClient share = new ShareClient(connectionString, shareName);
// Create the share if it doesn't already exist
await share.CreateIfNotExistsAsync();
// Ensure that the share exists
if (await share.ExistsAsync())
{
Console.WriteLine($"Share created: {share.Name}");
// Get a reference to the sample directory
ShareDirectoryClient directory = share.GetDirectoryClient("CustomLogs");
// Create the directory if it doesn't already exist
await directory.CreateIfNotExistsAsync();
// Ensure that the directory exists
if (await directory.ExistsAsync())
{
// Get a reference to a file object
ShareFileClient file = directory.GetFileClient("Log1.txt");
// Ensure that the file exists
if (await file.ExistsAsync())
{
Console.WriteLine($"File exists: {file.Name}");
// Download the file
ShareFileDownloadInfo download = await file.DownloadAsync();
// Save the data to a local file, overwrite if the file already exists
using (FileStream stream = File.OpenWrite(@"downloadedLog1.txt"))
{
await download.Content.CopyToAsync(stream);
await stream.FlushAsync();
stream.Close();
// Display where the file was saved
Console.WriteLine($"File downloaded: {stream.Name}");
}
}
}
}
else
{
Console.WriteLine($"CreateShareAsync failed");
}
}
Ustawianie maksymalnego rozmiaru udziału plików
Począwszy od wersji 5.x biblioteki klienta usługi Azure Files, można ustawić limit przydziału (maksymalny rozmiar) dla udziału plików. Można również sprawdzić, ile danych jest obecnie przechowywanych w udziale.
Ustawienie limitu przydziału udziału ogranicza całkowity rozmiar plików przechowywanych w udziale. Jeśli całkowity rozmiar plików w udziale przekracza limit przydziału, klienci nie mogą zwiększyć rozmiaru istniejących plików. Klienci nie mogą również tworzyć nowych plików, chyba że te pliki są puste.
W poniższym przykładzie pokazano, jak sprawdzić bieżące użycie udziału oraz jak ustawić limit przydziału w udziale.
//-------------------------------------------------
// Set the maximum size of a share
//-------------------------------------------------
public async Task SetMaxShareSizeAsync(string shareName, int increaseSizeInGiB)
{
const long ONE_GIBIBYTE = 10737420000; // Number of bytes in 1 gibibyte
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instantiate a ShareClient which will be used to access the file share
ShareClient share = new ShareClient(connectionString, shareName);
// Create the share if it doesn't already exist
await share.CreateIfNotExistsAsync();
// Ensure that the share exists
if (await share.ExistsAsync())
{
// Get and display current share quota
ShareProperties properties = await share.GetPropertiesAsync();
Console.WriteLine($"Current share quota: {properties.QuotaInGB} GiB");
// Get and display current usage stats for the share
ShareStatistics stats = await share.GetStatisticsAsync();
Console.WriteLine($"Current share usage: {stats.ShareUsageInBytes} bytes");
// Convert current usage from bytes into GiB
int currentGiB = (int)(stats.ShareUsageInBytes / ONE_GIBIBYTE);
// This line sets the quota to be the current
// usage of the share plus the increase amount
await share.SetQuotaAsync(currentGiB + increaseSizeInGiB);
// Get the new quota and display it
properties = await share.GetPropertiesAsync();
Console.WriteLine($"New share quota: {properties.QuotaInGB} GiB");
}
}
Generowanie sygnatury dostępu współdzielonego dla pliku lub udziału plików
Począwszy od wersji 5.x biblioteki klienta usługi Azure Files, można wygenerować sygnaturę dostępu współdzielonego dla udziału plików lub dla pojedynczego pliku.
Poniższa przykładowa metoda zwraca sygnaturę dostępu współdzielonego w pliku w określonym udziale.
//-------------------------------------------------
// Create a SAS URI for a file
//-------------------------------------------------
public Uri GetFileSasUri(string shareName, string filePath, DateTime expiration, ShareFileSasPermissions permissions)
{
// Get the account details from app settings
string accountName = ConfigurationManager.AppSettings["StorageAccountName"];
string accountKey = ConfigurationManager.AppSettings["StorageAccountKey"];
ShareSasBuilder fileSAS = new ShareSasBuilder()
{
ShareName = shareName,
FilePath = filePath,
// Specify an Azure file resource
Resource = "f",
// Expires in 24 hours
ExpiresOn = expiration
};
// Set the permissions for the SAS
fileSAS.SetPermissions(permissions);
// Create a SharedKeyCredential that we can use to sign the SAS token
StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, accountKey);
// Build a SAS URI
UriBuilder fileSasUri = new UriBuilder($"https://{accountName}.file.core.windows.net/{fileSAS.ShareName}/{fileSAS.FilePath}");
fileSasUri.Query = fileSAS.ToSasQueryParameters(credential).ToString();
// Return the URI
return fileSasUri.Uri;
}
Aby uzyskać więcej informacji na temat tworzenia i używania sygnatur dostępu współdzielonego, zobacz Jak działa sygnatura dostępu współdzielonego.
Kopiowanie plików
Począwszy od wersji 5.x biblioteki klienta usługi Azure Files, można skopiować plik do innego pliku, plik do obiektu blob lub obiekt blob do pliku.
Możesz również użyć narzędzia AzCopy, aby skopiować jeden plik do innego lub skopiować obiekt blob do pliku lub w drugą stronę. Zobacz Wprowadzenie do narzędzia AzCopy.
Uwaga
Jeśli kopiujesz obiekt blob do pliku lub pliku do obiektu blob, musisz użyć sygnatury dostępu współdzielonego (SAS), aby autoryzować dostęp do obiektu źródłowego, nawet jeśli kopiujesz w ramach tego samego konta magazynu.
Kopiowanie pliku do innego pliku
Poniższy przykładowy kod kopiuje plik do innego pliku w tym samym udziale. Możesz użyć uwierzytelniania klucza współdzielonego, aby wykonać kopię, ponieważ ta operacja kopiuje pliki na tym samym koncie magazynu.
//-------------------------------------------------
// Copy file within a directory
//-------------------------------------------------
public async Task CopyFileAsync(string shareName, string sourceFilePath, string destFilePath)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Get a reference to the file we created previously
ShareFileClient sourceFile = new ShareFileClient(connectionString, shareName, sourceFilePath);
// Ensure that the source file exists
if (await sourceFile.ExistsAsync())
{
// Get a reference to the destination file
ShareFileClient destFile = new ShareFileClient(connectionString, shareName, destFilePath);
// Start the copy operation
await destFile.StartCopyAsync(sourceFile.Uri);
if (await destFile.ExistsAsync())
{
Console.WriteLine($"{sourceFile.Uri} copied to {destFile.Uri}");
}
}
}
Kopiowanie pliku do obiektu blob
Poniższy przykładowy kod tworzy plik i kopiuje go do obiektu blob w ramach tego samego konta magazynu. Dla pliku źródłowego tworzona jest sygnatura dostępu współdzielonego, za pomocą której usługa autoryzuje dostęp do tego pliku podczas operacji kopiowania.
//-------------------------------------------------
// Copy a file from a share to a blob
//-------------------------------------------------
public async Task CopyFileToBlobAsync(string shareName, string sourceFilePath, string containerName, string blobName)
{
// Get a file SAS from the method created ealier
Uri fileSasUri = GetFileSasUri(shareName, sourceFilePath, DateTime.UtcNow.AddHours(24), ShareFileSasPermissions.Read);
// Get a reference to the file we created previously
ShareFileClient sourceFile = new ShareFileClient(fileSasUri);
// Ensure that the source file exists
if (await sourceFile.ExistsAsync())
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Get a reference to the destination container
BlobContainerClient container = new BlobContainerClient(connectionString, containerName);
// Create the container if it doesn't already exist
await container.CreateIfNotExistsAsync();
BlobClient destBlob = container.GetBlobClient(blobName);
await destBlob.StartCopyFromUriAsync(sourceFile.Uri);
if (await destBlob.ExistsAsync())
{
Console.WriteLine($"File {sourceFile.Name} copied to blob {destBlob.Name}");
}
}
}
W ten sam sposób można skopiować obiekt blob do pliku. Jeśli obiekt źródłowy jest obiektem blob, utwórz sygnaturę dostępu współdzielonego w celu autoryzacji dostępu do tego obiektu blob podczas operacji kopiowania.
Migawki udziałów
Począwszy od wersji 8.5 biblioteki klienta usługi Azure Files, można utworzyć migawkę udziału. Można również wyświetlać listę migawek udziałów oraz je przeglądać i usuwać. Po utworzeniu migawki udziałów są tylko do odczytu.
Tworzenie migawek udziałów
W poniższym przykładzie przedstawiono sposób tworzenia migawki udziału plików.
//-------------------------------------------------
// Create a share snapshot
//-------------------------------------------------
public async Task CreateShareSnapshotAsync(string shareName)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instatiate a ShareServiceClient
ShareServiceClient shareServiceClient = new ShareServiceClient(connectionString);
// Instantiate a ShareClient which will be used to access the file share
ShareClient share = shareServiceClient.GetShareClient(shareName);
// Ensure that the share exists
if (await share.ExistsAsync())
{
// Create a snapshot
ShareSnapshotInfo snapshotInfo = await share.CreateSnapshotAsync();
Console.WriteLine($"Snapshot created: {snapshotInfo.Snapshot}");
}
}
Wyświetlanie listy migawek udziałów
Poniższy przykład zawiera listę migawek w udziale.
//-------------------------------------------------
// List the snapshots on a share
//-------------------------------------------------
public void ListShareSnapshots()
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instatiate a ShareServiceClient
ShareServiceClient shareServiceClient = new ShareServiceClient(connectionString);
// Display each share and the snapshots on each share
foreach (ShareItem item in shareServiceClient.GetShares(ShareTraits.All, ShareStates.Snapshots))
{
if (null != item.Snapshot)
{
Console.WriteLine($"Share: {item.Name}\tSnapshot: {item.Snapshot}");
}
}
}
Wyświetlanie listy plików i katalogów w ramach migawek udziałów
Poniższy przykład umożliwia przeglądanie plików i katalogów w ramach migawek udziałów.
//-------------------------------------------------
// List the snapshots on a share
//-------------------------------------------------
public void ListSnapshotContents(string shareName, string snapshotTime)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instatiate a ShareServiceClient
ShareServiceClient shareService = new ShareServiceClient(connectionString);
// Get a ShareClient
ShareClient share = shareService.GetShareClient(shareName);
Console.WriteLine($"Share: {share.Name}");
// Get as ShareClient that points to a snapshot
ShareClient snapshot = share.WithSnapshot(snapshotTime);
// Get the root directory in the snapshot share
ShareDirectoryClient rootDir = snapshot.GetRootDirectoryClient();
// Recursively list the directory tree
ListDirTree(rootDir);
}
//-------------------------------------------------
// Recursively list a directory tree
//-------------------------------------------------
public void ListDirTree(ShareDirectoryClient dir)
{
// List the files and directories in the snapshot
foreach (ShareFileItem item in dir.GetFilesAndDirectories())
{
if (item.IsDirectory)
{
Console.WriteLine($"Directory: {item.Name}");
ShareDirectoryClient subDir = dir.GetSubdirectoryClient(item.Name);
ListDirTree(subDir);
}
else
{
Console.WriteLine($"File: {dir.Name}\\{item.Name}");
}
}
}
Przywracanie udziałów plików lub plików z migawek udziałów
Utworzenie migawki udziału plików umożliwia odzyskanie pojedynczych plików lub całego udziału plików.
Aby przywrócić plik z migawki udziału plików, można utworzyć zapytanie o migawki udziałów w udziale plików. Następnie możesz pobrać plik należący do określonej migawki udziału. Użyj tej wersji, aby bezpośrednio odczytać lub przywrócić plik.
//-------------------------------------------------
// Restore file from snapshot
//-------------------------------------------------
public async Task RestoreFileFromSnapshot(string shareName, string directoryName, string fileName, string snapshotTime)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instatiate a ShareServiceClient
ShareServiceClient shareService = new ShareServiceClient(connectionString);
// Get a ShareClient
ShareClient share = shareService.GetShareClient(shareName);
// Get as ShareClient that points to a snapshot
ShareClient snapshot = share.WithSnapshot(snapshotTime);
// Get a ShareDirectoryClient, then a ShareFileClient to the snapshot file
ShareDirectoryClient snapshotDir = snapshot.GetDirectoryClient(directoryName);
ShareFileClient snapshotFile = snapshotDir.GetFileClient(fileName);
// Get a ShareDirectoryClient, then a ShareFileClient to the live file
ShareDirectoryClient liveDir = share.GetDirectoryClient(directoryName);
ShareFileClient liveFile = liveDir.GetFileClient(fileName);
// Restore the file from the snapshot
ShareFileCopyInfo copyInfo = await liveFile.StartCopyAsync(snapshotFile.Uri);
// Display the status of the operation
Console.WriteLine($"Restore status: {copyInfo.CopyStatus}");
}
Usuwanie migawek udziałów
W poniższym przykładzie przedstawiono sposób usuwania migawki udziału plików.
//-------------------------------------------------
// Delete a snapshot
//-------------------------------------------------
public async Task DeleteSnapshotAsync(string shareName, string snapshotTime)
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instatiate a ShareServiceClient
ShareServiceClient shareService = new ShareServiceClient(connectionString);
// Get a ShareClient
ShareClient share = shareService.GetShareClient(shareName);
// Get a ShareClient that points to a snapshot
ShareClient snapshotShare = share.WithSnapshot(snapshotTime);
try
{
// Delete the snapshot
await snapshotShare.DeleteIfExistsAsync();
}
catch (RequestFailedException ex)
{
Console.WriteLine($"Exception: {ex.Message}");
Console.WriteLine($"Error code: {ex.Status}\t{ex.ErrorCode}");
}
}
Rozwiązywanie problemów z usługą Azure Files przy użyciu metryk
Usługa Azure analityka magazynu obsługuje metryki dla usługi Azure Files. Dane metryk umożliwiają śledzenie żądań i diagnozowanie problemów.
Metryki usługi Azure Files można włączyć w witrynie Azure Portal. Metryki można również włączyć programowo, wywołując operację Ustaw właściwości usługi plików za pomocą interfejsu API REST lub jedną z jej analogii w bibliotece klienta usługi Azure Files.
W poniższym przykładzie kodu pokazano, jak używać biblioteki klienta platformy .NET do włączania metryk dla usługi Azure Files.
//-------------------------------------------------
// Use metrics
//-------------------------------------------------
public async Task UseMetricsAsync()
{
// Get the connection string from app settings
string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];
// Instatiate a ShareServiceClient
ShareServiceClient shareService = new ShareServiceClient(connectionString);
// Set metrics properties for File service
await shareService.SetPropertiesAsync(new ShareServiceProperties()
{
// Set hour metrics
HourMetrics = new ShareMetrics()
{
Enabled = true,
IncludeApis = true,
Version = "1.0",
RetentionPolicy = new ShareRetentionPolicy()
{
Enabled = true,
Days = 14
}
},
// Set minute metrics
MinuteMetrics = new ShareMetrics()
{
Enabled = true,
IncludeApis = true,
Version = "1.0",
RetentionPolicy = new ShareRetentionPolicy()
{
Enabled = true,
Days = 7
}
}
});
// Read the metrics properties we just set
ShareServiceProperties serviceProperties = await shareService.GetPropertiesAsync();
// Display the properties
Console.WriteLine();
Console.WriteLine($"HourMetrics.InludeApis: {serviceProperties.HourMetrics.IncludeApis}");
Console.WriteLine($"HourMetrics.RetentionPolicy.Days: {serviceProperties.HourMetrics.RetentionPolicy.Days}");
Console.WriteLine($"HourMetrics.Version: {serviceProperties.HourMetrics.Version}");
Console.WriteLine();
Console.WriteLine($"MinuteMetrics.InludeApis: {serviceProperties.MinuteMetrics.IncludeApis}");
Console.WriteLine($"MinuteMetrics.RetentionPolicy.Days: {serviceProperties.MinuteMetrics.RetentionPolicy.Days}");
Console.WriteLine($"MinuteMetrics.Version: {serviceProperties.MinuteMetrics.Version}");
Console.WriteLine();
}
Jeśli wystąpią jakiekolwiek problemy, zapoznaj się z artykułem Rozwiązywanie problemów z usługą Azure Files.
Następne kroki
Aby uzyskać więcej informacji na temat usługi Azure Files, zobacz następujące zasoby:
- Wprowadzenie do narzędzia AzCopy
- Rozwiązywanie problemów z plikami platformy Azure
- Interfejsy API usługi Azure Storage dla platformy .NET
- Interfejs API REST usługi File (Plik)
Aby uzyskać powiązane przykłady kodu korzystające z przestarzałych zestawów SDK platformy .NET w wersji 11.x, zobacz Przykłady kodu korzystające z platformy .NET w wersji 11.x.