Copying/over-writing one source to another in TFS? - c#

Question Background:
Within my TF Server I have two folders, one is a simple 'HelloWorld.sln' in a folder called 'HelloWorldDev' and the other is a 'HelloWorld.sln' in a folder called 'HelloWorldQA'. Each folder contains its respective .cs files etc.
I want to checkout a file from the HelloWorld QA folder, replace - or update it - with a version from the HelloWorldDev folder with the same file name, then check this file back into the HelloWorldQA folder with the relevant changes.
Question:
I am very new to the TFS API so I'm not 100% if what I'm trying to ask is the correct way to proceed, or if its even possible. Can someone give me an example of achieving this?
Code so far:
string fileName = #"C:\Users\Me\Documents\TfsServer\HelloWorldQA\IHelloWorld.cs";
string fileNameQA = #"C:\Users\Me\Documents\TfsServer\HelloWorld\IHelloWorld.cs";
string uri = #"https://tfsServer.visualstudio.com/";
var workspaceInfo = Workstation.Current.GetLocalWorkspaceInfo(fileName);
var server = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
var workspace = workspaceInfo.GetWorkspace(server);
workspace.PendEdit(fileName);
FileInfo fi = new FileInfo(fileName);
var workspaceInfoQA = Workstation.Current.GetLocalWorkspaceInfo(fileNameQA);
var serverQA = new TfsTeamProjectCollection(workspaceInfo.ServerUri);
var workspaceQA = workspaceInfo.GetWorkspace(serverQA);
workspace.PendEdit(fileNameQA);
FileInfo fiQA = new FileInfo(fileNameQA);

First, instead of using 2 workspaces, you can simply map both folders in the same workspace.
Then you're looking for a merge operation:
var sourcePath = workspace.GetServerItemForLocalItem(fileName);
var targetPath = workspace.GetServerItemForLocalItem(fileNameQA);
var getStatus = workspace.Merge(sourcePath, targetPath, null, null);
if (getStatus.NumUpdated > 0)
{
//OK
}

Related

How can I access a local folder inside a WPF project to load and store files?

I need a library of vector files, where the same files have to be used every time. I want to load them from a folder and have the option to store new ones.
I tried having a library folder inside the WPF project that contains the files:
Solution/Project/Library/file1.dxf
I load them like this:
string currentDir = Directory.GetCurrentDirectory();
var cutOff = currentDir.LastIndexOf(#"\bin\");
var folder = currentDir.Substring(0, cutOff) + #"\Library\";
string[] filePaths = Directory.GetFiles(folder, "*.dxf");
This worked when running on the PC the project was buid, but the program crashes when the .exe is run on another PC. How do I fix this or is there a better approach to this?
Create a subfolder under Environment.SpecialFolder.ApplicationData, read the files in the library folder if it exists. If not create it and save the existing library files to it (here from resources):
string appFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string path = appFolder + #"\MyAppLibrary\";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
// Add existing files to that folder
var rm = Properties.Resources.ResourceManager;
var resSet = rm.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (var res in resSet)
{
var entry = ((DictionaryEntry)res);
var name = (string)entry.Key;
var file = (byte[])rm.GetObject(name);
var filePath = path + name + ".dxf";
File.WriteAllBytes(filePath, file);
}
}
// Load all files from the library folder
string[] filePaths = Directory.GetFiles(path, "*.dxf");
Thanks Jonathan Alfaro and Clemens!

Moving a SharePoint folder and contents to different location in same Document Library

I'm looking for a way to move a folder and all it's contents to a different location in the same library using the Client Object Model for SharePoint 2010 (C#).
For example we have a folder for a project (say 12345) and it's URL is
http://sharepoint/site/library/2012/12345
where 2012 represents a year. I'd like to programmatically move the 12345 folder to a different year, say 2014 which probably exists already but may not.
I've searched around but the solutions I'm getting seem extremely complicated and relevant to moving folders to different site collections, I'm hoping because it's in the same library there might be a simpler solution? One idea I have is to rely on Explorer View instead of CSOM?
Thanks a lot!
There is no built-in method in SharePoint CSOM API for moving Folder with Files from one location into another.
The following class represents how to move files from source folder into destination folder:
public static class FolderExtensions
{
public static void MoveFilesTo(this Folder folder, string folderUrl)
{
var ctx = (ClientContext)folder.Context;
if (!ctx.Web.IsPropertyAvailable("ServerRelativeUrl"))
{
ctx.Load(ctx.Web, w => w.ServerRelativeUrl);
}
ctx.Load(folder, f => f.Files, f => f.ServerRelativeUrl, f => f.Folders);
ctx.ExecuteQuery();
//Ensure target folder exists
EnsureFolder(ctx.Web.RootFolder, folderUrl.Replace(ctx.Web.ServerRelativeUrl, string.Empty));
foreach (var file in folder.Files)
{
var targetFileUrl = file.ServerRelativeUrl.Replace(folder.ServerRelativeUrl, folderUrl);
file.MoveTo(targetFileUrl, MoveOperations.Overwrite);
}
ctx.ExecuteQuery();
foreach (var subFolder in folder.Folders)
{
var targetFolderUrl = subFolder.ServerRelativeUrl.Replace(folder.ServerRelativeUrl,folderUrl);
subFolder.MoveFilesTo(targetFolderUrl);
}
}
public static Folder EnsureFolder(Folder parentFolder, string folderUrl)
{
var ctx = parentFolder.Context;
var folderNames = folderUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
var folderName = folderNames[0];
var folder = parentFolder.Folders.Add(folderName);
ctx.Load(folder);
ctx.ExecuteQuery();
if (folderNames.Length > 1)
{
var subFolderUrl = string.Join("/", folderNames, 1, folderNames.Length - 1);
return EnsureFolder(folder, subFolderUrl);
}
return folder;
}
}
Key points:
allows to ensure whether destination folder(s) exists
In case of nested folders, its structure is preserved while moving files
Usage
var srcFolderUrl = "/news/pages";
var destFolderUrl = "/news/archive/pages";
using (var ctx = new ClientContext(url))
{
var sourceFolder = ctx.Web.GetFolderByServerRelativeUrl(srcFolderUrl);
sourceFolder.MoveFilesTo(destFolderUrl);
sourceFolder.DeleteObject(); // delete source folder if nessesary
ctx.ExecuteQuery();
}
Just in case someone needs this translated to PnP PowerShell. It's not battle tested but works for me. Versions and metadata moved as well within the same library.
$list = Get-PnPList -Identity Documents
$web = $list.ParentWeb
$folder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTo"
$tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath "Shared Documents/MoveTwo"
function MoveFolder
{
[cmdletbinding()]
Param (
$web,
$fromFolder,
$toFolder
)
$fromFolder.Context.Load($fromFolder.Files)
$fromFolder.Context.Load($fromFolder.Folders)
$fromFolder.Context.ExecuteQuery()
foreach ($file in $fromFolder.Files)
{
$targetFileUrl = $file.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
$file.MoveTo($targetFileUrl, [Microsoft.SharePoint.Client.MoveOperations]::Overwrite);
}
$fromFolder.Context.ExecuteQuery();
foreach ($subFolder in $fromFolder.Folders)
{
$targetFolderUrl = $subFolder.ServerRelativeUrl.Replace($fromFolder.ServerRelativeUrl, $toFolder.ServerRelativeUrl);
$targetFolderRelativePath = $targetFolderUrl.SubString($web.RootFolder.ServerRelativeUrl.Length)
$tofolder = Ensure-PnPFolder -Web $list.ParentWeb -SiteRelativePath $targetFolderRelativePath
MoveFolder -Web $web -fromFolder $subFolder -toFolder $tofolder
}
}
$web.Context.Load($web.RootFolder)
$web.Context.ExecuteQuery()
MoveFolder -Web $web -fromFolder $folder -toFolder $tofolder
$folder.DeleteObject()
$web.Context.ExecuteQuery()

Moving files based on name to the corresponding folder

Hello everyone and well met! I have tried a lot of different methods/programs to try and solve my problem. I'm a novice programmer and have taken a Visual Basic Class and Visual C# class.
I'm working with this in C#
I started off by making a very basic move file program and it worked fine for one file but as I mentioned I will be needing to move a ton of files based on name
What I am trying to do is move .pst (for example dave.pst) files from my exchange server based on username onto a backup server in the users folder (folder = dave) that has the same name as the .pst file
The ideal program would be:
Get files from the folder with the .pst extension
Move files to appropriate folder that has the same name in front of the .pst file extension
Update:
// String pstFileFolder = #"C:\test\";
// var searchPattern = "*.pst";
// var extension = ".pst";
//var serverFolder = #"C:\test3\";
// String filename = System.IO.Path.GetFileNameWithoutExtension(pstFileFolder);
// Searches the directory for *.pst
DirectoryInfo sourceDirectory = new DirectoryInfo(#"C:\test\");
String strTargetDirectory = (#"C:\test3\");
Console.WriteLine(sourceDirectory);
Console.ReadKey(true);>foreach (FileInfo file in sourceDirectory.GetFiles()) {
Console.WriteLine(file);
Console.ReadKey(true);
// Try to create the directory.
System.IO.Directory.CreateDirectory(strTargetDirectory);
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}
This is just a simple copy procedure. I'm completely aware. The
Console.WriteLine(file);
Console.ReadKey(true);
Are for verification purpose right now to make sure I'm getting the proper files and I am. Now I just need to find the folder based on the name of the .pst file(the folder for the users are already created), make a folder(say 0304 for the year), then copy that .pst based on the name.
Thanks a ton for your help guys. #yuck, thanks for the code.
Have a look at the File and Directory classes in the System.IO namespace. You could use the Directory.GetFiles() method to get the names of the files you need to transfer.
Here's a console application to get you started. Note that there isn't any error checking and it makes some assumptions about how the files are named (e.g. that they end with .pst and don't contain that elsewhere in the name):
private static void Main() {
var pstFileFolder = #"C:\TEMP\PST_Files\";
var searchPattern = "*.pst";
var extension = ".pst";
var serverFolder = #"\\SERVER\PST_Backup\";
// Searches the directory for *.pst
foreach (var file in Directory.GetFiles(pstFileFolder, searchPattern)) {
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
// Gets the user name based on file name
// e.g. DaveSmith.pst would become DaveSmith
var userName = theFileInfo.Name.Replace(extension, "");
// Sets up the destination location
// e.g. \\SERVER\PST_Backup\DaveSmith\DaveSmith.pst
var destination = serverFolder + userName + #"\" + theFileInfo.Name;
File.Move(file, destination);
}
}
System.IO is your friend in this case ;)
First, Determine file name by:
String filename = System.IO.Path.GetFileNameWithoutExtension(SOME_PATH)
To make path to new folder, use Path.Combine:
String targetDir = Path.Combine(SOME_ROOT_DIR,filename);
Next, create folder with name based on given fileName
System.IO.Directory.CreateDirectory(targetDir);
Ah! You need to have name of file, but with extension this time. Path.GetFileName:
String fileNameWithExtension = System.IO.Path.GetFileName(SOME_PATH);
And you can move file (by File.Move) to it:
System.IO.File.Move(SOME_PATH,Path.Combine(targetDir,fileNameWithExtension)
Laster already show you how to get file list in folder.
I personally prefer DirectoryInfo because it is more object-oriented.
DirectoryInfo sourceDirectory = new DirectoryInfo("C:\MySourceDirectoryPath");
String strTargetDirectory = "C:\MyTargetDirectoryPath";
foreach (FileInfo file in sourceDirectory.GetFiles())
{
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}

How to record files on a server with minimal access using MVC

How to record files on a server with minimal access using MVC. The next version of the code is not suitable as it will be clogging up the domain.
Controller code:
var fileFile = Request.Files["p" + prop.Id];
if (fileFile == null) continue;
string pathFile = AppDomain.CurrentDomain.BaseDirectory + "UploadedFiles";
string filenameFile = Path.GetFileName(fileFile.FileName);
if (filenameFile != null) fileFile.SaveAs(Path.Combine(pathFile, filenameFile));
(if it is possible to realize this by putting file to the cache)
EDITED CODE:
var ordinaryPropertyValue = new Catalog.Core.Entities.OrdinaryPropertyValue();
Environment.CurrentDirectory = Environment.GetEnvironmentVariable("TEMP");
var fileFile = Request.Files["File" + prop.Id];
if (fileFile == null) continue;
string pathFile = Environment.CurrentDirectory;
fileFile.SaveAs(pathFile);
ordinaryPropertyValue.Value = pathFile;
instance.SetPropertyValue(prop.Id, ordinaryPropertyValue);
You could use the common application data location (this would be better than %TEMP% if you need them to stick around - people have a tendency to clean the %TEMP% folder out from time to time in my experience) - all users should have access to that and then you could just put it in a sub-folder like so:
var appDataFolder = System.Environment.GetFolderPath(SpecialFolder.CommonApplicationData);
var dir = Path.Combine(Path.Combine(appDataFolder, "My Application"), "UploadedFiles"):
// save your files into dir
Here are all the "special folders" in case you see one that you would rather use: Environment.SpecialFolder

How to read a text file in project's root directory?

I want to read the first line of a text file that I added to the root directory of my project. Meaning, my solution explorer is showing the .txt file along side my .cs files in my project.
So, I tried to do:
TextReader tr = new StreamReader(#"myfile.txt");
string myText = tr.ReadLine();
But this doesn't work since it's referring to the Bin Folder and my file isn't in there... How can I make this work? :/
Thanks
From Solution Explorer, right click on myfile.txt and choose "Properties"
From there, set the Build Action to content
and Copy to Output Directory to either Copy always or Copy if newer
You can use the following to get the root directory of a website project:
String FilePath;
FilePath = Server.MapPath("/MyWebSite");
Or you can get the base directory like so:
AppDomain.CurrentDomain.BaseDirectory
Add a Resource File to your project (Right Click Project->Properties->Resources). Where it says "strings", you can switch to be "files". Choose "Add Resource" and select your file.
You can now reference your file through the Properties.Resources collection.
private string _filePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);
The method above will bring you something like this:
"C:\Users\myuser\Documents\Visual Studio 2015\Projects\myProjectNamespace\bin\Debug"
From here you can navigate backwards using System.IO.Directory.GetParent:
_filePath = Directory.GetParent(_filePath).FullName;
1 time will get you to \bin, 2 times will get you to \myProjectNamespace, so it would be like this:
_filePath = Directory.GetParent(Directory.GetParent(_filePath).FullName).FullName;
Well, now you have something like "C:\Users\myuser\Documents\Visual Studio 2015\Projects\myProjectNamespace", so just attach the final path to your fileName, for example:
_filePath += #"\myfile.txt";
TextReader tr = new StreamReader(_filePath);
Hope it helps.
You can have it embedded (build action set to Resource) as well, this is how to retrieve it from there:
private static UnmanagedMemoryStream GetResourceStream(string resName)
{
var assembly = Assembly.GetExecutingAssembly();
var strResources = assembly.GetName().Name + ".g.resources";
var rStream = assembly.GetManifestResourceStream(strResources);
var resourceReader = new ResourceReader(rStream);
var items = resourceReader.OfType<DictionaryEntry>();
var stream = items.First(x => (x.Key as string) == resName.ToLower()).Value;
return (UnmanagedMemoryStream)stream;
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
string resName = "Test.txt";
var file = GetResourceStream(resName);
using (var reader = new StreamReader(file))
{
var line = reader.ReadLine();
MessageBox.Show(line);
}
}
(Some code taken from this answer by Charles)
You have to use absolute path in this case. But if you set the CopyToOutputDirectory = CopyAlways, it will work as you are doing it.
In this code you access to root directory project:
string _filePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);
then:
StreamReader r = new StreamReader(_filePath + "/cities2.json"))

Categories