At the moment I have a number of containers. Foreach container I want to add an empty folder from a different storage account just containing the folders name. I then want to populate it with the necessary data.
I'm not sure if there is an property that can create a folder within a container.
Here I have two containers one from my sourceAccount and the other to my targetAccount. I'm sending data from my sourceAccout to my tagetAccount. In my target account within my container dayBlob I want to create the sub folder.
In this section of code I'm getting all the containers. When I get these containers I get the name of each of them. I want to add sub folders in my target container with the names that I get in my foreach
foreach (var items in containers)
{
var containerName = items.Name;
}
My code is as follows
static CloudStorageAccount sourceAccount = new CloudStorageAccount(new StorageCredentials("name", "key"), true);
static CloudStorageAccount targertAccount = new CloudStorageAccount(new StorageCredentials("name", "key"), true);
static void Main(string[] args)
{
DateTime dateToday = DateTime.Today;
DateTime date = new DateTime();
DateTime dateutc = TimeZoneInfo.ConvertTimeToUtc(date);
TimeSpan startDay = new TimeSpan(00, 00, 00);
TimeSpan endDay = new TimeSpan(23, 59, 59);
var sourceClient = sourceAccount.CreateCloudBlobClient();
var targetClient = targetAccount.CreateCloudBlobClient();
var testContainer = sourceClient.GetContainerReference("test");
var sourceContainer = sourceClient.GetContainerReference("downloads");
var itDropBoxContainer = sourceClient.GetContainerReference("it-dropbox");
var dayBlob = targetClient.GetContainerReference($"day{dateToday.Day}");
date = DateTime.Parse($"{dateToday.Day}/{dateToday.Month}/{dateToday.Year}");
var start = date + startDay;
var end = date + endDay;
IEnumerable<CloudBlobContainer> containers = sourceClient.ListContainers();
foreach (var items in containers)
{
var containerName = items.Name;
}
foreach (IListBlobItem item in testContainer.ListBlobs(useFlatBlobListing: true))
{
var blob = item as CloudBlockBlob;
var modificationDate = blob.Properties.LastModified;
// to set the modfication date as local time
var britishZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var lastModified = TimeZoneInfo.ConvertTime((DateTimeOffset)modificationDate, britishZone);
if (lastModified > start && lastModified < end)
{
try
{
if (blob != null)
{
CloudBlockBlob sourceBlob = testContainer.GetBlockBlobReference(blob.Name);
CloudBlockBlob targetBlob = dayBlob.GetBlockBlobReference(blob.Name);
Console.WriteLine($"Successfully created a snapshot of blob {blob.Name}");
}
}
catch (Exception ex)
{
ExceptionHandler.LogError(ex, "Failed to copy to the target folder");
}
}
else
{
Console.WriteLine($"Failed to create a snapshot of blob {blob.Name}");
}
}
}
As #GauravMantri mentioned, we can't create folder without independently because folder is a virtual entity in blob storage. You don't need to create a folder before using it. For example, we can get the reference of folder1 even if the folder1 is not exist in the container.
var directory = container.GetDirectoryReference("folder1");
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = directory.GetBlockBlobReference("myblob");
If you did want to create a folder, you did need to create a blob within it.
var directory = container.GetDirectoryReference("folder1");
CloudBlockBlob blockBlob = directory.GetBlockBlobReference("dummy.txt");
blockBlob.UploadFromByteArray(new byte[0], 0, 0);
To list all the folders in a container, you could use following code.
var folders = container.ListBlobs().Where(b => b as CloudBlobDirectory != null).ToList();
foreach (var folder in folders)
{
Console.WriteLine(folder.Uri);
}
Related
I try upload file to provided Azure containers which it is taken from ProvisionMigrationContainers() method, however it was not successful.
I am using below C# code:
ClientContext clientContext = new ClientContext(urlSring);
var securePassword = new SecureString();
foreach (var c in passWord) securePassword.AppendChar(c);
clientContext.Credentials = new SharePointOnlineCredentials(userName, securePassword);
ClientResult<ProvisionedMigrationContainersInfo> containerInfo = clientContext.Site.ProvisionMigrationContainers();
clientContext.ExecuteQuery();
var containerInfoList = containerInfo.Value;
var dataContainerUri = containerInfoList.DataContainerUri;
var metadataContainerUri = containerInfoList.MetadataContainerUri;
CloudBlobContainer dataContainer = new CloudBlobContainer(new Uri(dataContainerUri));
CloudBlobContainer manifestContainer = new CloudBlobContainer(new Uri(metadataContainerUri));
//Upload data to container start
var testfiles = new[]
{
new SourceFile
{
Filename = "test.txt",
LastModified = DateTime.Now,
Contents = Encoding.UTF8.GetBytes("Hi, this is a test text-file"),
Title = "Title of file 1"
},
new SourceFile
{
Filename = "test2.txt",
LastModified = DateTime.Now.AddDays(-1),
Contents = Encoding.UTF8.GetBytes("Tesfile2"),
Title = "Second title"
}
};
foreach (var testfile in testfiles)
{
var blobReference = dataContainer.GetBlockBlobReference(testfile.Filename);
blobReference.UploadFromByteArray(testfile.Contents, 0, testfile.Contents.Length);
}
When i get list blob from provided Azure containers with below code, it returns null.
var blobList = dataContainer.ListBlobs();
var fileList = blobList.OfType<CloudBlockBlob>().Select(x => x.Name).ToList();
Would you please tell me the reason?
Thanks in advance
RonLee.
I have following code which will return all list items (files and folders) of specific given azure storage path.
I want to filter it using OrderByDescending based on Property LastModified
How to achieve this ?
// Get list of all files/directories on the file share
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["storageConnectionString"]);
CloudFileClient fileClient = cloudStorageAccount.CreateCloudFileClient();
CloudFileShare fileShare = fileClient.GetShareReference(ConfigurationManager.AppSettings["shareName"]);
var sourceName = fileShare.GetRootDirectoryReference().GetDirectoryReference((ConfigurationManager.AppSettings["sourceName"]));
IEnumerable<IListFileItem> fileList = sourceName.ListFilesAndDirectories();
var test = (fileList.OrderByDescending(t => t.Uri.AbsolutePath).FirstOrDefault());
I tried with casting but LastModified is null
fileList.ToList().ForEach(x => ((CloudFileDirectory)x).FetchAttributes());
GetAllSubDir(fileList.OrderByDescending(t => ((CloudFileDirectory)t).Properties.LastModified.Value).FirstOrDefault());
instead of Uri.AbsolutePath I want to use LastModified.
Have a try at following code. You need to get all files first because ListFilesAndDirectories only returns files and directory in a single level.
List<CloudFile> list = new List<CloudFile>();
public void Test()
{
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["storageConnectionString"]);
CloudFileClient fileClient = cloudStorageAccount.CreateCloudFileClient();
CloudFileShare fileShare =
fileClient.GetShareReference(ConfigurationManager.AppSettings["shareName"]);
var sourceName = fileShare.GetRootDirectoryReference().GetDirectoryReference((ConfigurationManager.AppSettings["sourceName"]));
IEnumerable<IListFileItem> fileList = sourceName.ListFilesAndDirectories();
listFile(fileList);
var test = (from file in list
orderby file.Properties.LastModified descending
select file).FirstOrDefault();
}
// detect all files in the directory
public void listFile(IEnumerable<IListFileItem> results)
{
foreach (IListFileItem fileItem in results)
{
if (fileItem.GetType() == typeof(CloudFileDirectory))
{
CloudFileDirectory directory = (CloudFileDirectory)fileItem;
var res = directory.ListFilesAndDirectories();
listFile(res);
}
else
{
CloudFile file = (CloudFile)fileItem;
file.FetchAttributes();
list.Add(file);
}
}
}
public static void CheckDate()
{
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["storageConnectionString"]);
CloudFileClient fileClient = cloudStorageAccount.CreateCloudFileClient();
CloudFileShare fileShare =
fileClient.GetShareReference(ConfigurationManager.AppSettings["shareName"]);
var sourceName = fileShare.GetRootDirectoryReference().GetDirectoryReference((ConfigurationManager.AppSettings["sourceName"]));
IEnumerable<IListFileItem> fileList = sourceName.ListFilesAndDirectories();
listFile(fileList);
var latestFile = (from file in filedataList
orderby file.Properties.LastModified descending
select file).FirstOrDefault();
Console.WriteLine(" LastModified Datetime - " + latestFile.Properties.LastModified.Value.DateTime);
}
public static void listFile(IEnumerable<IListFileItem> results)
{
foreach (var item in results)
{
if (item.GetType() == typeof(CloudFileDirectory))
{
CloudFileDirectory dir = (CloudFileDirectory)item;
dir.FetchAttributes();
dirList.Add(dir);
}
else
{
CloudFile file = (CloudFile)item;
file.FetchAttributes();
filedataList.Add(file);
}
}
if (dirList.Count > 0)
{
var latestDir = (from dir in dirList
orderby dir.Properties.LastModified descending
select dir).FirstOrDefault();
dirList.Clear();
var result = latestDir.ListFilesAndDirectories();
listFile(result);
}
}
I need to get current iteration's path from TFS project. I'm able to use REST API query <server>/<project>/_apis/work/teamsettings/iterations?$timeframe=current&api-version=v2.0-preview but I don't want to perform query and parse JSON response. I want to use appropriate API in .NET client libraries for VSTS (and TFS).
I have an instance of the VssConnection. How can I get the path of current iteration from this object?
You can get the current iteration using the WorkHttpClient without having to iterate:
var creds = new VssBasicCredential(string.Empty, "personalaccesstoken");
VssConnection connection = new VssConnection(new Uri("url"), creds);
var workClient = connection.GetClient<WorkHttpClient>();
var teamContext = new TeamContext(teamId);
teamContext.ProjectId = projectId;
var currentIteration = await workClient.GetTeamIterationsAsync(teamContext, "current");
The simplest way I've found to do it was by using ICommonStructureService4 and TeamSettingsConfigurationService methods:
static TfsTeamProjectCollection _tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection("<tfsUri>")
(...)
static string GetCurrentIterationPath()
{
var css = _tfs.GetService<ICommonStructureService4>();
var teamProjectName = "<teamProjectName>";
var project = css.GetProjectFromName(teamProjectName);
var teamName = "<teamName>";
var teamSettingsStore =
_tfs.GetService<TeamSettingsConfigurationService>();
var settings = teamSettingsStore
.GetTeamConfigurationsForUser(new[] { project.Uri })
.Where(c => c.TeamName == teamName)
.FirstOrDefault();
if (settings == null)
{
var currentUser = System.Threading.Thread.CurrentPrincipal.Identity.Name;
throw new InvalidOperationException(
$"User '{currentUser}' doesn't have access to '{teamName}' team project.");
}
return settings.TeamSettings.CurrentIterationPath;
}
And returning the TeamSettings.CurrentIterationPath property.
I found a solution using VssConnection:
var workClient = connection.GetClient<WorkHttpClient>();
var iterations = workClient.GetTeamIterationsAsync(new TeamContext("project-name")).Result;
var currentDate = DateTime.Now.Date;
var currentIterationPath = iterations
.Select(i => new { i.Path, i.Attributes })
.FirstOrDefault(i => currentDate >= i.Attributes.StartDate &&
currentDate <= i.Attributes.FinishDate)
?.Path;
Here is a case provides a solution: Get the current iteration path from TFS
private static XmlNode currentIterationNode;
TfsTeamProjectCollection tpc = TFSConncetion(#"http://tfs/url");
ICommonStructureService4 css = tpc.GetService<ICommonStructureService4>();;
WorkItemStore workItemStore = new WorkItemStore(tpc);
foreach (Project teamProject in workItemStore.Projects)
{
if (teamProject.Name.Equals("TeamProjectNameGoesHere"))
{
NodeInfo[] structures = css.ListStructures(teamProject.Uri.ToString());
NodeInfo iterations = structures.FirstOrDefault(n => n.StructureType.Equals("ProjectLifecycle"));
if (iterations != null)
{
XmlElement iterationsTree = css.GetNodesXml(new[] { iterations.Uri }, true);
XmlNodeList nodeList = iterationsTree.ChildNodes;
currentIterationNode = FindCurrentIteration(nodeList);
String currentIterationPath = currentIterationNode.Attributes["Path"].Value;
}
}
}
I want to collect the directory listing in a collection(a List<> perhaps)
my directory structure is like :
MainFolder\ParentFolder1\SubFolder1
\SubFolder2
\SubFolder3
MainFolder\ParentFolder2\SubFolder1
\SubFolder2
\SubFolder3
I want to list all the subfolders mapped to their parent directories.
Also, the records will have index of ParentFolder 0-n in MainFolder and index of SubFolder 0-n in each ParentFolder.
I did tried below but not yet achieved
lstParents = (from f in Directory.GetDirectories(MainFolder)
select Data
{
parent =f
}).ToList();
var lstSubDir = (from f in lstParents.Select(m => Directory.GetDirectories(m.parent).ToList());
You can use this overload of the GetDirectories method to find all subdirectories recursively:
var mainDirectory = new DirectoryInfo(#"C:\temp\MainFolder");
var subDirectories = mainDirectory.GetDirectories("*", SearchOption.AllDirectories);
Then you can map them into pairs of directory/parent like this:
var mappedDirectories = subDirectories.Select(sd => new { Parent=sd.Parent, Child=sd });
If you want to exclude the first level of subdirectories (ParentFolder1 and ParentFolder2, in your case) you can filter them like this:
var mappedDirectories = subDirectories
.Where(sd => sd.Parent.FullName != mainDirectory.FullName)
.Select(sd => new { Parent=sd.Parent, Child=sd });
EDIT after you've asked for indices:
You stated, that you'll always only have a nesting level of 2, the following piece of code will not work for deeper directory structures.
var mainDirectory = new DirectoryInfo(#"C:\temp\MainFolder");
var firstLevelDirectories = mainDirectory.GetDirectories().Select((f1,i) => new {
Parent = f1,
ParentIndex = i
});
var secondLevelDirectories = firstLevelDirectories
.SelectMany(f1 => f1.Parent.GetDirectories().Select((f2,i) => new {
f1.Parent,
f1.ParentIndex,
Child = f2,
ChildIndex = i
} ));
This will give you a list of records, each containing
the parent directory,
the parent directory index,
the child directory and
the child directory index within its parent.
Try this recursive algorithm.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Folders folders = new Folders(#"c:\temp", null);
Console.ReadLine();
}
}
public class Folders
{
public string path { get; set; }
List<string> files = new List<string>();
List<Folders> folders = new List<Folders>();
Folders parent = null;
public Folders(string path, Folders parent)
{
this.parent = parent;
this.path = path;
foreach (string folderPath in Directory.GetDirectories(path))
{
Folders newFolder = new Folders(folderPath, this);
folders.Add(newFolder);
}
files = Directory.GetFiles(path).ToList();
int pathlength = path.Length;
Boolean first = true;
Console.Write(path);
if (files.Count == 0) Console.WriteLine();
foreach (string file in files)
{
string shortname = file.Substring(file.LastIndexOf("\\") + 1);
if (first)
{
Console.WriteLine("\\" + shortname);
first = false;
}
else
{
Console.WriteLine(new string(' ', pathlength + 1) + shortname);
}
}
}
}
}
I've got the following code:
private void ListCalendarFolders(ref List<EBCalendar> items, int offset)
{
var pageSize = 100;
var view = new FolderView(pageSize, offset, OffsetBasePoint.Beginning);
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(FolderSchema.DisplayName);
view.PropertySet.Add(FolderSchema.EffectiveRights);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot, view);
foreach (Folder myFolder in findFolderResults.Folders)
{
if (myFolder is CalendarFolder)
{
var folder = myFolder as CalendarFolder;
items.Add(EBCalendar.FromEWSFolder(folder));
}
}
if (findFolderResults.MoreAvailable)
{
offset = offset + pageSize;
ListCalendarFolders(ref items, offset);
}
}
Where service is an ExchangeService instance. Unfortunately, it still lists folders that have been deleted, and it doesn't list shared calendars.
How can I get it to list all the shared calendars, and how can I get it to not include the folders that have been deleted?
By Shared Calendars do you mean the calendars under the other calendars node in Outlook ?
If so these Items are NavLinks that are stored in the Common Views folder in a Mailbox which is under the NonIPMSubtree (root) see http://msdn.microsoft.com/en-us/library/ee157359(v=exchg.80).aspx. You can use EWS to get the NavLinks from a Mailbox and use the PidTagWlinkAddressBookEID extended property to get the X500 address of the Mailbox these Links refer to and then use Resolve Name to resolve that to a SMTP Address. Then all you need to do is Bind to that folder eg
static Dictionary<string, Folder> GetSharedCalendarFolders(ExchangeService service, String mbMailboxname)
{
Dictionary<String, Folder> rtList = new System.Collections.Generic.Dictionary<string, Folder>();
FolderId rfRootFolderid = new FolderId(WellKnownFolderName.Root, mbMailboxname);
FolderView fvFolderView = new FolderView(1000);
SearchFilter sfSearchFilter = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, "Common Views");
FindFoldersResults ffoldres = service.FindFolders(rfRootFolderid, sfSearchFilter, fvFolderView);
if (ffoldres.Folders.Count == 1)
{
PropertySet psPropset = new PropertySet(BasePropertySet.FirstClassProperties);
ExtendedPropertyDefinition PidTagWlinkAddressBookEID = new ExtendedPropertyDefinition(0x6854, MapiPropertyType.Binary);
ExtendedPropertyDefinition PidTagWlinkGroupName = new ExtendedPropertyDefinition(0x6851, MapiPropertyType.String);
psPropset.Add(PidTagWlinkAddressBookEID);
ItemView iv = new ItemView(1000);
iv.PropertySet = psPropset;
iv.Traversal = ItemTraversal.Associated;
SearchFilter cntSearch = new SearchFilter.IsEqualTo(PidTagWlinkGroupName, "Other Calendars");
// Can also find this using PidTagWlinkType = wblSharedFolder
FindItemsResults<Item> fiResults = ffoldres.Folders[0].FindItems(cntSearch, iv);
foreach (Item itItem in fiResults.Items)
{
try
{
object GroupName = null;
object WlinkAddressBookEID = null;
// This property will only be there in Outlook 2010 and beyond
//https://msdn.microsoft.com/en-us/library/ee220131(v=exchg.80).aspx#Appendix_A_30
if (itItem.TryGetProperty(PidTagWlinkAddressBookEID, out WlinkAddressBookEID))
{
byte[] ssStoreID = (byte[])WlinkAddressBookEID;
int leLegDnStart = 0;
// Can also extract the DN by getting the 28th(or 30th?) byte to the second to last byte
//https://msdn.microsoft.com/en-us/library/ee237564(v=exchg.80).aspx
//https://msdn.microsoft.com/en-us/library/hh354838(v=exchg.80).aspx
String lnLegDN = "";
for (int ssArraynum = (ssStoreID.Length - 2); ssArraynum != 0; ssArraynum--)
{
if (ssStoreID[ssArraynum] == 0)
{
leLegDnStart = ssArraynum;
lnLegDN = System.Text.ASCIIEncoding.ASCII.GetString(ssStoreID, leLegDnStart + 1, (ssStoreID.Length - (leLegDnStart + 2)));
ssArraynum = 1;
}
}
NameResolutionCollection ncCol = service.ResolveName(lnLegDN, ResolveNameSearchLocation.DirectoryOnly, false);
if (ncCol.Count > 0)
{
FolderId SharedCalendarId = new FolderId(WellKnownFolderName.Calendar, ncCol[0].Mailbox.Address);
Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
rtList.Add(ncCol[0].Mailbox.Address, SharedCalendaFolder);
}
}
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
}
return rtList;
}
Cheers
Glen
You need to specify a searchfilter.
this is described here, though im not sure which Schema is the correct one, my guess would be Archieved.
So you would do something like this:
SearchFilter searchFilter = new SearchFilter.IsEqualTo(FolderSchema.Archieved, false);
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot,searchFilter, view);
Glen post is perfect but binding folder gives error. However i solved this. Instead of this line:
Folder SharedCalendaFolder = Folder.Bind(service, SharedCalendarId);
use the following line for shared folder binding
CalendarFolder calendar = CalendarFolder.Bind(service, new FolderId(WellKnownFolderName.Calendar, OwnerEmailAddress), new PropertySet());
Here OwnerEmailAddress is Email Address of Owner or you can write ncCol[0].Mailbox.Address if using Glen's code.