I am struggling to get solution folder names in the TFS drop locations.
I have a .NET solution file in the following hirerchy:
Solution File
--> Solution Folder A --> Project A
--> Solution Folder B --> Project B & Project C
Now I want my drop location should be customized like the above project hierarchy.
means : in the Drop Location it should be : SolutionName -> SolutionFolderName -> ProjectName -> {build output}
By implementing customize output directory in my build template , i.e. $(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName), I am getting Solution Name -> Project Name -> Build outputs..
But I am not getting Solution Folder names to structure my outputs. Can anybody suggest how to get this so that I can read from my project files.
Thanks in advance.
You could set a property in the projects that corresponds to the solution folder name (e.g. $(SolutionFolder)). Then you could set the output directory to $(TeamBuildOutDir)\$(SolutionFolder).
public static TeamProject[] GetAllProjects(TfsTeamProjectCollection prjCollection)
{
var versionControl = prjCollection.GetService<VersionControlServer>();
return versionControl.GetAllTeamProjects(true);
}
public static ProjectCollection GetAllIterations(TfsTeamProjectCollection prjCollection)
{
var wiStore = prjCollection.GetService<WorkItemStore>();
return wiStore.Projects;
}
/// <summary>
/// function to get all system project name
/// </summary>
private void IterateFolder()
{
try
{ var selectedProject = "EMRConversion";
Project detailsOfTheSelectedProject = null;
var projCollections = GetAllIterations(prjCollection);
foreach (Project project in projCollections)
{
if (!String.IsNullOrEmpty(selectedProject))
{
if (project.Name.ToString().Contains(selectedProject))
{
detailsOfTheSelectedProject = project;
break;
}
}
}
if (detailsOfTheSelectedProject != null)
{
cmbSystemName.Items.Clear();
foreach (Node area in detailsOfTheSelectedProject.AreaRootNodes)
{
if (!(area.HasChildNodes))
{
cmbSystemName.Items.Add(area.Name);
}
foreach (Node item in area.ChildNodes)
{
cmbSystemName.Items.Add(item.Name);
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
Related
I have Xamarin Forms solution and in Xamarin Droid project I have custom renderer for class CustomCameraScanView that extends ContentView. This CustomCameraScanView should use Camera (old API) on Androids before 5.0 (Lollipop) and Camera2 (new API) from 5.0 and afterwards. How can I create two renderers: CustomCameraScanViewRenderer_Droid4 and CustomCameraScanViewRenderer_Droid5 that will be used on different versions of OS?
My CustomCameraScanViewRenderer_Droid4 looks like this:
[assembly: ExportRenderer(typeof(CustomCameraScanView), typeof(CustomCameraScanViewRenderer_Droid4))]
namespace Genea.Droid.Renderers
{
public class CustomCameraScanViewRenderer_Droid4 : ViewRenderer,
ISurfaceTextureListener,
ISurfaceHolderCallback,
Android.Hardware.Camera.IPreviewCallback,
Android.Hardware.Camera.IPictureCallback,
Android.Hardware.Camera.IShutterCallback
{
}
}
Unfortunately, registering a custom-renderer at runtime is not possible at this point in Xamarin-Forms. More details can be found on this forum link. But what you can do is resolve the controls at run-time using OnPlatform and build-version number.
I would of course recommend the conditional-compilation approach first as suggested by #luccas-clezar; but if that is not an option, then you can try resolving your control (and hence the renderer) at run-time using following steps.
Steps:
Create an simple contract to resolve current API value - in forms project
public interface IBuildVersion { int Number { get; } }
Implement it for Android platform
public class AndroidBuildVersion : IBuildVersion
{
public int Number { get { return ((int)Android.OS.Build.VERSION.SdkInt); } }
}
Register on DependencyService
[assembly: Xamarin.Forms.Dependency (typeof (AndroidBuildVersion))]
Subclass your CustomCameraScanView into two derived types - in forms project
public class CustomCameraScanView_Droid4 : CustomCameraScanView { }
public class CustomCameraScanView_Droid5 : CustomCameraScanView { }
Setup your renderers in Android project
[assembly: ExportRenderer(typeof(CustomCameraScanView_Droid4), typeof(CustomCameraScanViewRenderer_Droid4))]
and,
[assembly: ExportRenderer(typeof(CustomCameraScanView_Droid5), typeof(CustomCameraScanViewRenderer_Droid5))]
Create custom-control to resolve at run-time - using OnPlatform - in forms project
public class CameraScanContentView : Xamarin.Forms.ContentView
{
public CameraScanContentView()
{
this.Content = Device.OnPlatform(
iOS: new CustomCameraScanView(),
Android: DependencyService.Get<IBuildVersion>().Number < 21
? ((CustomCameraScanView)new CustomCameraScanView_Droid4())
: ((CustomCameraScanView)new CustomCameraScanView_Droid5()),
WinPhone: new CustomCameraScanView()
);
}
}
And, XAML usage will look like this
<local:CameraScanContentView />
Update 05/24
I don't believe Xamarin-Forms supports 'Property Value' inheritance as WPF does - so it is kind of tricky to propagate the values from parent to child control.
One option is to cascade these values back to CustomCameraScanView from CameraScanContentView by defining bindable-properties (recommended):
public class CameraScanContentView : Xamarin.Forms.ContentView
{
public CameraScanContentView()
{
CustomCameraScanView scannerCtrl = null;
switch (Device.RuntimePlatform)
{
case Device.Android:
scannerCtrl = DependencyService.Get<IBuildVersion>().Number < 21
? ((CustomCameraScanView)new CustomCameraScanView_Droid4())
: ((CustomCameraScanView)new CustomCameraScanView_Droid5());
break;
default:
scannerCtrl = new CustomCameraScanView();
break;
}
scannerCtrl.SetBinding(CustomCameraScanView.IsScanningProperty, new Binding(nameof(IsScanning), source: this));
scannerCtrl.SetBinding(CustomCameraScanView.IsTakingImageProperty, new Binding(nameof(IsTakingImage), source: this));
scannerCtrl.SetBinding(CustomCameraScanView.IsFlashlightOnProperty, new Binding(nameof(IsFlashlightOn), source: this));
Content = scannerCtrl;
}
public static readonly BindableProperty IsScanningProperty = BindableProperty.Create("IsScanning", typeof(bool), typeof(CameraScanContentView), false);
public static readonly BindableProperty IsTakingImageProperty = BindableProperty.Create("IsTakingImage", typeof(bool), typeof(CameraScanContentView), false);
public static readonly BindableProperty IsFlashlightOnProperty = BindableProperty.Create("IsFlashlightOn", typeof(bool), typeof(CameraScanContentView), false);
public bool IsScanning
{
get { return (bool)GetValue(IsScanningProperty); }
set { SetValue(IsScanningProperty, value); }
}
public bool IsTakingImage
{
get { return (bool)GetValue(IsTakingImageProperty); }
set { SetValue(IsTakingImageProperty, value); }
}
public bool IsFlashlightOn
{
get { return (bool)GetValue(IsFlashlightOnProperty); }
set { SetValue(IsFlashlightOnProperty, value); }
}
}
XAML usage will then look like this
<local:CameraScanContentView IsScanning="{Binding IsScanning}" IsFlashlightOn="{Binding IsFlashlightOn}" IsTakingImage="{Binding IsTakingImage}" />
Or, you can manually define your binding-expressions as below (not recommended as it makes the assumption that the property-names on view-model will not change):
public class CameraScanContentView : Xamarin.Forms.ContentView
{
public CameraScanContentView()
{
CustomCameraScanView scannerCtrl = null;
switch (Device.RuntimePlatform)
{
case Device.Android:
scannerCtrl = DependencyService.Get<IBuildVersion>().Number < 21
? ((CustomCameraScanView)new CustomCameraScanView_Droid4())
: ((CustomCameraScanView)new CustomCameraScanView_Droid5());
break;
default:
scannerCtrl = new CustomCameraScanView();
break;
}
scannerCtrl.SetBinding(CustomCameraScanView.IsScanningProperty, new Binding("IsScanning", source: this.BindingContext));
scannerCtrl.SetBinding(CustomCameraScanView.IsTakingImageProperty, new Binding("IsTakingImage", source: this.BindingContext));
scannerCtrl.SetBinding(CustomCameraScanView.IsFlashlightOnProperty, new Binding("IsFlashlightOn", source: this.BindingContext));
Content = scannerCtrl;
}
}
Note: My first instinct was to use an implicit style targeting CustomCameraScanView to bind the values - but somehow couldn't get it to work.
There's no need to have two renderers I think. Something like this should work:
if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
{
// Access old API
}
else
{
// Access new API
}
Another method of doing the same thing is by adding compiler directives. Like so:
#if __ANDROID_21__
// New API (>=21)
#else
// Old API (<21)
#endif
This will compile only the specific code of that Android API. I'm not sure if this works with PCL projects and the only thing that I could find that said something about it is this line from Dealing with Multiple Platforms guide: "Conditional compilation works best with Shared Asset Projects, where the same source file is being referenced in multiple projects that have different symbols defined.". Anyway, I think you could give it a try.
Hope it helps! :)
You will probably have to put some code like the code below inside the renderers so their methods don't get called unless a certain platform requirement is met:
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
// Lollipop specific stuff
}
There is no mechanism in place to actually point to a different renderer on different OS versions.
You can put the following code in your main activity right after Forms.Init() (if you are using forms)
if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
Xamarin.Forms.Internals.Registrar.Registered.Register(typeof(Xamarin.Forms.Picker), typeof(PickerRendererEx));
}
else
{
Xamarin.Forms.Internals.Registrar.Registered.Register(typeof(Xamarin.Forms.Picker), typeof(PickerRendererExOld));
}
I would like to create a separate help page for each version of my API. For example, the user could go to /help?v=1 to see version 1.0 routes and /help?v=2 to see version 2.0 routes.
Using SDammann.WebApi.Versioning, I added a Version property to VersionedApiExplorer that will return only the routes for the defined version and added the version as an argument to the constructor. Then I tried this:
config.Services.Add(typeof(IApiExplorer), new VersionedApiExplorer(config, "1"));
config.Services.Add(typeof(IApiExplorer), new VersionedApiExplorer(config, "2"));
But this gives me the following error:
The service type IApiExplorer is not supported.
Parameter name: serviceType
I added just one instance of the service - config.Services.Replace(typeof(IApiExplorer), new VersionedApiExplorer(GlobalConfiguration.Configuration, "1")); - to get the configuration to work, so I could test my help controller. Then tried this:
foreach (var service in Configuration.Services.GetServices(typeof(IApiExplorer))) {
if (service.GetType() != typeof(VersionedApiExplorer)) continue;
var explorer = service as VersionedApiExplorer;
if (explorer.Version == v) {
apiExplorer = explorer;
}
}
This gives the same error I received above. I know I would normally use this.Configuration.Services.GetApiExplorer() but I don't know how I could use that to get the appropriate instance of VersionedApiExplorer. I know I could instantiate the appropriate ApiExplorer directly in the controller, but I would prefer to keep that in my configuration file if possible.
So I have two questions:
How could I add two services of type VersionedApiExplorer to my config object?
How would I retrieve the appropriate service in my help controller?
Or is there a completely different approach I could take to accomplish the same goal?
Thank you!
I ultimately ended up going with the solution I hinted at in my question. I feel like there's a better solution to this problem, but this gets the job done.
First, I added a Version property to VersionedApiExplorer:
public string Version { get; private set; }
Then I modified InitializeApiDescriptions to look like this:
private Collection<ApiDescription> InitializeApiDescriptions()
{
Collection<ApiDescription> apiDescriptions = new Collection<ApiDescription>();
var controllerSelector = configuration.Services.GetHttpControllerSelector();
IDictionary<string, HttpControllerDescriptor> allControllerMappings = controllerSelector.GetControllerMapping();
IDictionary<string, HttpControllerDescriptor> controllerMappings = new Dictionary<string, HttpControllerDescriptor>();
// get only mappings for defined version
if (allControllerMappings != null && Version != null) {
foreach (var key in allControllerMappings.Keys) {
if (key.Substring(0, key.IndexOf('.')) == VersionedControllerSelector.VersionPrefix + Version) {
controllerMappings.Add(key, allControllerMappings[key]);
}
}
}
else if (Version == null) {
controllerMappings = allControllerMappings;
}
if (controllerMappings != null)
{
foreach (var route in configuration.Routes)
ExploreRouteControllers(controllerMappings, route, apiDescriptions);
}
return apiDescriptions;
}
I also added a method I could use to set the Version:
public void SetVersion(string version) {
this.Version = version;
this.apiDescription = new Lazy<Collection<ApiDescription>>(InitializeApiDescriptions);
}
Finally, I modified my HelpController to looks like this:
public ActionResult Index(string v) {
return this.View(GetApiExplorer(v).ApiDescriptions);
}
private IApiExplorer GetApiExplorer(string version) {
if (version == null) {
version = "1";
}
var apiExplorer = this.Configuration.Services.GetApiExplorer() as VersionedApiExplorer;
if (apiExplorer != null) {
apiExplorer.SetVersion(version);
}
return apiExplorer;
}
I have some projects in a Visual Studio solution that have ended up with project references that include the wrong GUID for the referenced project. (Possibly due to the referenced project being recreated at some stage)
eg. Consider a project CoreProject.csproj with the following properties:
<ProjectGuid>{93803F9C-8C65-4949-8D44-AB7A3D0452C8}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>CoreProject</RootNamespace>
<AssemblyName>CoreProject</AssemblyName>
Another project includes a reference to this, but at some stage the GUID has changed and is now incorrect.
<ProjectReference Include="..\CoreProject\CoreProject.csproj">
<Project>{5FD52517-79F8-41D2-B6F2-EA2D8A886549}</Project>
<Name>CoreProject</Name>
</ProjectReference>
The solution still loads and builds correctly in Visual Studio and msbuild, but I suspect having the wrong GUIDs may have some performance impact within VS.
The solution is quite large with many projects that have this issue, and I'd prefer not to have to re-add these references manually. Are there any tools or macros that can 'fix' up the project reference GUIDs?
I think a basic console app should do the trick, something like this:
using System;
using System.IO;
using System.Linq;
using Microsoft.Build.Evaluation;
public class Program
{
public static void Main(String[] args)
{
var projects = Directory.EnumerateFiles(#"...", "*.csproj", SearchOption.AllDirectories)
.Select(x =>
{
try
{
return new Project(x);
}
catch
{
return null;
}
})
.Where(x => x != null)
.ToList();
var guids = projects.ToDictionary(p => p.FullPath, p => p.GetPropertyValue("ProjectGuid"));
foreach (var project in projects)
{
var save = false;
foreach (var reference in project.GetItems("ProjectReference"))
{
var path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(project.FullPath), reference.EvaluatedInclude));
if (!guids.ContainsKey(path))
{
Console.WriteLine("No {0}", Path.GetFileName(path));
continue;
}
var guid = guids[path];
var meta = reference.GetMetadataValue("Project");
if (meta != guid)
{
Console.WriteLine("{0} -> {1}", meta, guid);
reference.SetMetadataValue("Project", guid);
save = true;
}
}
if (save)
project.Save(project.FullPath);
}
}
}
We are trying to move a file to an FTP site. We need to create a folder structure like this:
/deeply/nested/folder/structure/index.html
Yesterday, we realized we can't create more than one folder at a time, so this doesn't work:
MKD /deeply/nested/folder/structure
So, in code, we wrote a loop that created each folder, one at a time, ignoring errors caused by the folder already existing. Ignoring errors is gross.
Is a way to create these nested folders in one action, rather than multiple? Is there a command to see if a folder already exists? If we just push the file out including the full path, will FTP be smart enough to create the directories for me?
No, there's no standard way to create a folder with subfolders. There's also no standard way to check if directory exists. You would need to use LIST or MLSD (where supported) and parse the result for this. Can't you just use some third-party component that supports the needed functionality?
I wrote a simple C# example here, maybe someone will need this code.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
namespace Deployer
{
public class RecursiveFolderUploader
{
private const string SrcFullPath = #"C:\prg\Snowinmars\Snowinmars.Ui";
private readonly IList<string> foldersOnServer;
private Client ftpClient; // that's your ftp client, init it
public RecursiveFolderUploader()
{
this.foldersOnServer = new List<string>();
}
private void UploadAll(DirectoryInfo directoryInfo)
{
// ftp://login:password#127.0.0.1/path/to/root/mydir/anotherdir/file.dat
// ^________________uri_______________________^_relevationPath_^
foreach (var file in directoryInfo.EnumerateFiles())
{
if (!file.Directory.FullName.StartsWith(RecursiveFolderUploader.SrcFullPath))
{
throw new InvalidOperationException($"File {file.FullName} is not from {RecursiveFolderUploader.SrcFullPath} folder");
}
string relevationPath; // all folders from root up to file
if (file.Directory.FullName.Length == RecursiveFolderUploader.SrcFullPath.Length)
{
relevationPath = "";
}
else
{
relevationPath = file.Directory.FullName.Substring(RecursiveFolderUploader.SrcFullPath.Length, file.Directory.FullName.Length - RecursiveFolderUploader.SrcFullPath.Length);
if (relevationPath.StartsWith("\\"))
{
relevationPath = relevationPath.Remove(0, 1);
}
}
string destination;
if (string.IsNullOrWhiteSpace(relevationPath))
{
destination = file.Name;
}
else
{
destination = Path.Combine(relevationPath, file.Name).Replace("\\", "/");
}
try
{
ftpClient.UploadFile(file.FullName, destination);
}
catch (WebException e)
{
// that means that there's no such folder or something else goes wrong
// we can check it by creating folders and try again
var parts = relevationPath.Replace("\\", "/").Split('/');
for (int i = 1; i <= parts.Length; i++)
{
var path = string.Join("/", parts.Take(i));
if (!foldersOnServer.Contains(path))
{
ftpClient.MakeDirectory(path);
foldersOnServer.Add(path);
}
}
try
{
ftpClient.UploadFile(file.FullName, destination);
}
catch (Exception innerE)
{
// if it doesn't help - trouble isn't in folders
throw new WebException($"Can't find folder {relevationPath}", innerE);
}
}
}
foreach (var directory in directoryInfo.EnumerateDirectories())
{
UploadAll(directory);
}
}
}
}
I have a project in my VS 2008 solution containing file items. Each item have a standard read only property called "FullPath" in the Properties Grid.
What is the easiest way to make the FullPath property of the Properties Grid editable?
Add reference to System.Design
Create class
public class DllFileNameEditor :
System.Windows.Forms.Design.FileNameEditor { protected override void InitializeDialog(OpenFileDialog openFileDialog)
{
base.InitializeDialog(openFileDialog);
openFileDialog.Filter = "Class Library Files (*.dll) |*.dll|All (*.*) |*.*";
openFileDialog.Title = "Select Class Library File";
} }
Modify property
[Category("Identity")]
[Description("Dll Location")]
[EditorAttribute(typeof(DllFileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string DllName
{
get { return this.GraphDoc.DllName; }
set { this.GraphDoc.DllName = value; }
}
mgznet.com/EditFullPathProperty.aspx