PropertyGrid ValueEditor for a file name - visual-studio

I have the following rule definition:
<Rule ...>
<... />
<StringProperty Subtype="file" ...>
<StringProperty.ValueEditors>
<ValueEditor EditorType="DefaultStringPropertyEditor" DisplayName="<Edit...>"/>
<ValueEditor EditorType="DefaultFilePropertyEditor" DisplayName="<Browse...>"/>
</StringProperty.ValueEditors>
</StringProperty>
<... />
</Rule>
It adds the "<Edit...>" and "<Browse...>" options for editing a property, but the Browse dialog asks for an *.exe file, when I need to let user select a *.txt file. There is a combobox in the dialog that allows to choose "All files .", but really that's not an option.
I have tried to find a solution but this extensibility bit does not seem to be well documented.

I have finally found a way to do that, yet for VS2012 only. Putting a metadata piece named Filters with the filters string in the typical open file dialog format seems to do the trick now.
Example:
<ValueEditor EditorType="DefaultFilePropertyEditor" DisplayName="<Browse...>">
<ValueEditor.Metadata>
<NameValuePair Name="Filters" Value="Text (*.txt)|*.txt" />
</ValueEditor.Metadata>
</ValueEditor>

Related

Displaying Metarunner parameters for build steps

I've created a metarunner in TeamCity, but I can't figure out how to display information from it on the list of build steps, which leads to several identical rows. Other (built-in) runners have the ability to display some basic information to help clarify what the step is doing. For example, in the image below, I have:
A metarunner with no description
The built-in Command Line task, with a "Command" displayed
Five instances of the same metarunner with different parameters, which all look the same.
The built-in SMB Upload task, with a "Target SMB share" displayed
One parameter from the "Copy config" metarunner looks like:
<param name="FileName" spec="text display='normal' label='File Name' description='Name of the file to be copied'" />
Is this something that can be edited via the metarunner XML? Or is this a feature that's only available to built-in runners?
I see parameters/param tags before the build-runners/runner section containing parameters/param (the latter being inputs to the wrapped runner, I guess). The former allow editable inputs. I am new so I feel uncomfortable with the multiple inheritance. I would rather see the parameters configuration from the runner to show up in the Parameters section of the build. I would also prefer if the runner could configure the artifact mapping as well. So far I am going to configure parameters in the root project separately from my custom runner. I did not look at custom plugins.
https://github.com/endjin/NewRelicDeploymentNotifierMetaRunner/blob/master/Solutions/SimpleRunner/server/metaRunners/MRPLUGIN_NewRelicDeploymentNotifier.xml
I figured I do not have to HTML-escape special characters in the runner's custom script, I could use the CDATA marker-wrapped clear text of the script as the param tag's text.
<build-runners>
<runner name="Run my runner" type="simpleRunner">
<parameters>
<param name="use.custom.script" value="true" />
<param name="script.content"><![CDATA[#echo on
if not exist %env.CYGBINSLASH%python2.7.exe (
powershell "$r = New-Object System.Net.WebClient; $r.DownloadFile('%env.scriptweb%fixcygwin.bat', 'fixcygwin.bat')"
call fixcygwin.bat /f
) 1>&2
#rem CMD.EXE would destroy leading double quotes in continuation lines, so sticking white space.
%env.CYGBINSLASH%bash -exc '^
if [[ "${my_param}" != "true" ]] ; then ^
exit; ^
fi; ^
/usr/bin/curl -o myscript.sh "${MY_SCRIPT}"; ^
source myscript.sh "PROJ_%Project%" "%Project%/%Project%.csproj"; ^
' 1>&2]]></param>
<param name="teamcity.step.mode" value="default" />
</parameters>
</runner>
</build-runners>

code reuse for file existence test in a Visual Studio vcxproj file

I have a vcxproj file that contains explicit Windows shell commands in the NMakeBuildCommandLine section:
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
move file1 file2
</NMakeBuildCommandLine>
I'm using MSBuild to execute the vcxproj, either directly or via a sln file. The problem is that when file1 does not exist, the output is very unhelpful and doesn't even list the file's name:
The system cannot find the file specified.
My naive solution is to replace move file1 file2 with:
if exist file1 (move file1 file2) else (echo file1 does not exist && exit 1)
(Note that I need to write && instead of &&.)
This works, but it's error-prone because I need to type file1 three times per line and make sure they all match. file1 is only one of many files that need to be moved. Furthermore, the series of commands is virtually identical across the various build configurations.
How can I avoid repeating myself both within a command line and across build configurations? I thought that the UserMacros property group might help me, but I couldn't figure out how to write such a macro via the IDE. (Right-clicking on the project in Visual Studio doesn't show a field for entering user macros.) Nor could I find any discussion of the syntax of this section on the Internet, so I didn't know how to write macros with a text editor (which I would actually prefer).
There may be yet a better way within a vcxproj file to identify files that need to exist, so I'm open to any alternatives.
MsBuild has 'variables' like most other programming languages called properties. You declare one in a PropertyGroup element in the project file xml and then reuse it using the $(PropertyName) syntax. Example for your case:
<PropertyGroup>
<Src>/path/to/my/src</Src>
<Dst>/path/to/my/dst</Dst>
</PropertyGroup>
<NMakeBuildCommandLine>
if exist $(Src) (move $(Src) $(Dst)) else (echo $(Src) does not exist && exit 1)
</NMakeBuildCommandLine>
If you want to use the IDE, which might get tedious if you have lots of values, you can indeed use so-called UserMacros but you have to declare those in a proprty sheet. Go to View->Property Manager, right-click on your project and select 'Add new Property Sheet'. Doubleclick on it, go to 'User Macros' and add key/value pairs there. If you save everything and look in the generated files you'll see the vcxproj now Imports the propertysheet, and the propertysheet itself has a PropertyGroup just like shown above - but editable thgough the IDE.
As an alternative which might be better (less duplication, easier to automate) in the long run you can use MsBuild code for checking file existence and moving files which has the benefit you only have to write the move command once as you can have MsBuild loop over items. Those are declared in an ItemGroup. Explaining everything here is a bit out of scope but an example should make things clear:
<Target Name="BatchMove">
<ItemGroup>
<SrcFiles Include="file1">
<Dest>file2</Dest>
</SrcFiles>
<SrcFiles Include="file3">
<Dest>file4</Dest>
</SrcFiles>
</ItemGroup>
<Warning Text="Source file %(SrcFiles.Identity) does not exist" Condition="!Exists(%(SrcFiles.Identity))" />
<Move SourceFiles="%(SrcFiles.Identity)" DestinationFiles="%(SrcFiles.Dest)" Condition="Exists(%(SrcFiles.Identity))" />
</Target>
This declares 2 source files file1/file3 and their respective destination files file2/file4. If the source does not exists (using standard MsBuild Exists check) a message is shown, else it is moved to the destination. Those % characters will make the line they occur in loop over each element of the SrcFiles collection. To add more files, just add to the ItemGroup. Last step is to get this target invoked from the nmake command line which is done simply by calling msbuild on the file itself and telling it to run the target:
<NMakeBuildCommandLine>
msbuild $(MSBuildThisFile) /t:BatchMove
</NMakeBuildCommandLine>

Change some fields in a file

I need to analyses a file and change some fields.
Example:
<taskdef uri="xxxxxx" resource="/mnt/data/yyy.xml">
<classpath path="/mnt/data/test.jar"/>
</taskdef>
<target name="test"
description="this is a xml file">
<fileset dir="/tmp/data/output/test_1/" includes=all/>
In my case I need to find this part:
<fileset dir="/tmp/data/output/test_1/" includes=all/>
and change just the name (for example) test_1
At the end, save the file
In your comment you say you "cannot use libraries like Nogokiri to parse the file". So I can only guess you're not doing full XML parsing.
Assuming you do not have to parse XML you could just use Ruby's String.replace method on the line in question. Just iterate over the lines in the file until you get to the one in quesion and call replace. Here's some pseudocode.
open file
for each line
is this what I want to change
change line
save (new) file

How to get Chirpy to update mashed files when edits are made

I've just begun using Chirpy, and it's frigging amazing. One problem I'm having is that I'm unable to get it to update the mashed file(s) when an edit is made in one of the "sub" files.
IE: If I have a mashed file called "site.css" (via my js.chirp.config file) which contains "elements.css", "master.css", "misc.css" etc. And I make an edit to one of them (say, master.css), I want chirpy to kick in and redo the site.css with the new edits.
Is this at all possible?
Chirpy does this - just make sure your paths use backslashes rather than forward slashes.
<root>
<FileGroup Name="site.css">
<File Path="css\elements.css" />
<File Path="css\master.css" />
<File Path="css\misc.css" />
</FileGroup>
</root>
Chirpity chirp chirp chirp.
I have
<Folder Pattern="*.min.css" Minify="false" />
And with that wildcard in there, it doesnt run when min.css files are updated. I have to update the config and save for the mash to occur

How to fully clean bin and obj folders within Visual Studio?

If you right click on a folder, you will see a "Clean" menu item. I assumed this would clean (remove) the obj and bin directory.
However, as far as I can see, it does nothing.
Is there another way?
(please don't tell me to go to Windows Explorer or the cmd.exe)
I'd like to remove the obj and bin folder so that I can easily zip the whole thing.
As others have responded already Clean will remove all artifacts that are generated by the build. But it will leave behind everything else.
If you have some customizations in your MSBuild project this could spell trouble and leave behind stuff you would think it should have deleted.
You can circumvent this problem with a simple change to your .*proj by adding this somewhere near the end :
<Target Name="SpicNSpan"
AfterTargets="Clean">
<RemoveDir Directories="$(OUTDIR)"/>
</Target>
Which will remove everything in your bin folder of the current platform/configuration.
------ Edit
Slight evolution based on Shaman's answer below (share the votes and give him some too)
<Target Name="SpicNSpan" AfterTargets="Clean">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
---- Edit again with parts from xDisruptor but I removed the .vs deletion as this would be better served in a .gitignore (or equivalent)
Updated for VS 2015.
<Target Name="SpicNSpan" AfterTargets="Clean"> <!-- common vars https://msdn.microsoft.com/en-us/library/c02as0cs.aspx?f=255&MSPPError=-2147217396 -->
<RemoveDir Directories="$(TargetDir)" /> <!-- bin -->
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" /> <!-- obj -->
</Target>
He also provides a good suggestion on making the task easier to deploy and maintain if you have multiple projects to push this into.
If you vote this answer be sure to vote them both as well.
If you are using git and have a correct .gitignore in your project, you can
git clean -xdf --dry-run
to remove absolutely every file on the .gitignore list, i.e. it will clean obj, and bin folders (the x triggers this behavior)
Note: The parameter --dry-run will only simulate the operation ("Would remove ...") and show you what git would delete. Try it with dry-run, then remove the parameter and it will really delete the files+folders.
Optionally, after that clean command, you can use dotnet restore mySolution.sln to get all the NUGET packages restored. And if you have a developer console open anyway, you can quickly run msbuild -m mySolution.sln afterwards (without having Visual Studio open) to see if it was successful.
For Visual Studio 2015 the MSBuild variables have changed a bit:
<Target Name="SpicNSpan" AfterTargets="Clean"> <!-- common vars https://msdn.microsoft.com/en-us/library/c02as0cs.aspx?f=255&MSPPError=-2147217396 -->
<RemoveDir Directories="$(TargetDir)" /> <!-- bin -->
<RemoveDir Directories="$(SolutionDir).vs" /> <!-- .vs -->
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" /> <!-- obj -->
</Target>
Notice that this snippet also wipes out the .vs folder from the root directory of your solution. You may want to comment out the associated line if you feel that removing the .vs folder is an overkill. I have it enabled because I noticed that in some third party projects it causes issues when files ala application.config exist inside the .vs folder.
Addendum:
If you are into optimizing the maintainability of your solutions you might want to take things one step further and place the above snippet into a separate file like so:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SpicNSpan" AfterTargets="Clean"> <!-- common vars https://msdn.microsoft.com/en-us/library/c02as0cs.aspx?f=255&MSPPError=-2147217396 -->
<RemoveDir Directories="$(TargetDir)" /> <!-- bin -->
<RemoveDir Directories="$(SolutionDir).vs" /> <!-- .vs -->
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" /> <!-- obj -->
</Target>
</Project>
And then include this file at the very end of each and every one of your *.csproj files like so:
[...]
<Import Project="..\..\Tools\ExtraCleanup.targets"/>
</Project>
This way you can enrich or fine-tune your extra-cleanup-logic centrally, in one place without going through the pains of manually editing each and every *.csproj file by hand every time you want to make an improvement.
To delete bin and obj before build add to project file:
<Target Name="BeforeBuild">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
Here is article: How to remove bin and/or obj folder before the build or deploy
This site: https://sachabarbs.wordpress.com/2014/10/24/powershell-to-clean-visual-studio-binobj-folders/ uses William Kempf's powershell commands to remove any bin and obj folders from the current directory and sub directories. It should be possible to run it from the root of the drive.
Here is William's version
gci -inc bin,obj -rec | rm -rec -force
In William's own words:
That wipes out all of the “bin” and “obj” directories in the current
directory and every subdirectory. Super useful to run in your
workspace directory to get to a “clean” state, especially when someone
messes up and there’s something that a Clean or Rebuild inside the IDE
doesn’t catch.
For those of you reading that may not know, PowerShell supports
command aliases, here it is rewritten again not using the aliases
Get-ChildItem -inc bin,obj -rec | Remove-Item -rec -force
NOTE : You should have this stored in a PowerShell file and place that
file at the root of your solution (where the .sln file resides), and
then run it when you want a proper clean (not the micky mouse one that
VisualStudio does, and reports success too).
Check out Ron Jacobs fantastic open source CleanProject It even takes care of the zipping if you like.
Here is the CodePlex link
Visual Studio Extension
Right Click Solution - Select "Delete bin and obj folders"
You can easily find and remove bin and obj folders in Far Manager.
Navigate to you solution and press Alt+F7
In search setting dialog:
Type "bin,obj" in field "A file mask or several file masks"
Check option "Search for folders"
Press Enter
After the search is done, switch view to "Panel".
Select all files (with Ctrl+A) and delete folders (press "Shift+Del")
Hope it helps someone.
Based on Joe answer, I've converted the VB code into C# :
/// <summary>
/// Based on code of VSProjCleaner tool (C) 2005 Francesco Balena, Code Archirects
/// </summary>
static class VisualStudioCleaner
{
public static void Process(string rootDir)
{
// Read all the folder names in the specified directory tree
string[] dirNames = Directory.GetDirectories(rootDir, "*.*", SearchOption.AllDirectories);
List<string> errorsList = new List<string>();
// delete any .suo and csproj.user file
foreach (string dir in dirNames) {
var files = new List<string>();
files.AddRange(Directory.GetFiles(dir, "*.suo"));
files.AddRange(Directory.GetFiles(dir, "*.user"));
foreach (string fileName in files) {
try {
Console.Write("Deleting {0} ...", fileName);
File.Delete(fileName);
Console.WriteLine("DONE");
} catch (Exception ex) {
Console.WriteLine();
Console.WriteLine(" ERROR: {0}", ex.Message);
errorsList.Add(fileName + ": " + ex.Message);
}
}
}
// Delete all the BIN and OBJ subdirectories
foreach (string dir in dirNames) {
string dirName = Path.GetFileName(dir).ToLower();
if (dirName == "bin" || dirName == "obj") {
try {
Console.Write("Deleting {0} ...", dir);
Directory.Delete(dir, true);
Console.WriteLine("DONE");
} catch (Exception ex) {
Console.WriteLine();
Console.WriteLine(" ERROR: {0}", ex.Message);
errorsList.Add(dir + ": " + ex.Message);
}
}
}
Console.WriteLine(new string('-', 60));
if (errorsList.Count == 0) {
Console.WriteLine("All directories and files were removed successfully");
} else {
Console.WriteLine("{0} directories or directories couldn't be removed", errorsList.Count);
Console.WriteLine(new string('-', 60));
foreach (string msg in errorsList) {
Console.WriteLine(msg);
}
}
}
}
In windows just open the explorer
navigate to your SLN folder
click into search field and type kind:=folder;obj --> for obj folders
use CTRL+A and delete 'em - same for bin
Done
No need for any tool or extra software ;)
Clean will remove all intermediate and final files created by the build process, such as .obj files and .exe or .dll files.
It does not, however, remove the directories where those files get built.
I don't see a compelling reason why you need the directories to be removed.
Can you explain further?
If you look inside these directories before and after a "Clean", you should see your compiled output get cleaned up.
I use VisualStudioClean which is easy to understand and predictable. Knowing how it works and what files it is going to delete relieves me.
Previously I tried VSClean (note VisualStudioClean is not VSClean), VSClean is more advanced, it has many configurations that sometimes makes me wondering what files it is going to delete? One mis-configuration will result in lose of my source codes. Testing how the configuration will work need backing up all my projects which take a lot of times, so in the end I choose VisualStudioClean instead.
Conclusion : VisualStudioClean if you want basic cleaning, VSClean for more complex scenario.
I can't add a comment yet (no minimal reputation reached)
so I leave this reply to underline that:
the "BeforeBuild" action with <RemoveDir Directories="$(BaseIntermediateOutputPath)" /> is great but, for me, is conflicting with an Entity Framework model included into the same project.
The error I receive is:
Error reading resource '{mymodel}.csdl' -- 'Could not find a part of the path '{myprojectpath}\obj\Release\edmxResourcesToEmbed\{mymodel}.csdl
I suppose, the "edmxResourcesToembed" is created before the "BeforeBuild" target action is executed.
This is how I do with a batch file to delete all BIN and OBJ folders recursively.
Create an empty file and name it DeleteBinObjFolders.bat
Copy-paste code the below code into the DeleteBinObjFolders.bat
Move the DeleteBinObjFolders.bat file in the same folder with your solution (*.sln) file.
#echo off
#echo Deleting all BIN and OBJ folders...
for /d /r . %%d in (bin,obj) do #if exist "%%d" rd /s/q "%%d"
#echo BIN and OBJ folders successfully deleted :) Close the window.
pause > nul
Update: Visual Studio 2019 (Clean [bin] and [obj] before release). However I am not sure if [obj] needs to be deleted. Be aware there is nuget package configuration placed too. You can remove the second line if you think so.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(Configuration)' == 'Release'">
<!--remove bin-->
<Exec Command="rd /s /q "$(ProjectDir)$(BaseOutputPath)" && ^" />
<!--remove obj-->
<Exec Command="rd /s /q "$(BaseIntermediateOutputPath)Release"" />
</Target>
I store my finished VS projects by saving only source code.
I delete BIN, DEBUG, RELEASE, OBJ, ARM and .vs folders from all projects.
This reduces the size of the project considerably. The project
must be rebuilt when pulled out of storage.
Just an addendum to all the fine answers above in case someone doesn't realize how easy it is in VB/C# to automate the entire process down to the zip archive.
So you just grab a simple Forms app from the templates (if you don't already have a housekeeping app) and add a button to it and then ClickOnce install it to your desktop without worrying about special settings or much of anything. This is all the code you need to attach to the button:
Imports System.IO.Compression
Private Sub btnArchive_Click(sender As Object, e As EventArgs) Handles btnArchive.Click
Dim src As String = "C:\Project"
Dim dest As String = Path.Combine("D:\Archive", "Stub" & Now.ToString("yyyyMMddHHmmss") & ".zip")
If IsProjectOpen() Then 'You don't want Visual Studio holding a lock on anything while you're deleting folders
MsgBox("Close projects first, (expletive deleted)", vbOKOnly)
Exit Sub
End If
If MsgBox("Are you sure you want to delete bin and obj folders?", vbOKCancel) = DialogResult.Cancel Then Exit Sub
If ClearBinAndObj(src) Then ZipFile.CreateFromDirectory(src, dest)
End Sub
Public Function ClearBinAndObj(targetDir As String) As Boolean
Dim dirstodelete As New List(Of String)
For Each d As String In My.Computer.FileSystem.GetDirectories(targetDir, FileIO.SearchOption.SearchAllSubDirectories, "bin")
dirstodelete.Add(d)
Next
For Each d As String In My.Computer.FileSystem.GetDirectories(targetDir, FileIO.SearchOption.SearchAllSubDirectories, "obj")
dirstodelete.Add(d)
Next
For Each d In dirstodelete
Try
Directory.Delete(d, True)
Catch ex As Exception
If MsgBox("Error: " & ex.Message & " - OK to continue?", vbOKCancel) = MsgBoxResult.Cancel Then Return False
End Try
Next
Return True
End Function
Public Function IsProjectOpen()
For Each clsProcess As Process In Process.GetProcesses()
If clsProcess.ProcessName.Equals("devenv") Then Return True
Next
Return False
End Function
One thing to remember is that file system deletes can go wrong easily. One of my favorites was when I realized that I couldn't delete a folder because it contained items created by Visual Studio while running with elevated privileges (so that I could debug a service).
I needed to manually give permission or, I suppose, run the app with elevated privileges also. Either way, I think there is some value in using an interactive GUI-based approach over a script, specially since this is likely something that is done at the end of a long day and you don't want to find out later that your backup doesn't actually exist...
this answer is great I just want to comment on the last part of the answer
NOTE : You should have this stored in a PowerShell file and place that
file at the root of your solution (where the .sln file resides), and
then run it when you want a proper clean (not the micky mouse one that
VisualStudio does, and reports success too).
Alternatively, you can add the following to your profile.ps1
function CleanSolution {
Get-ChildItem -inc bin,obj -rec | Remove-Item -rec -force
}
Set-Alias cs CleanSolution
Then you can use either CleanSolution or cs to run. That way you can use it for any project and without the ./ prefix of the filename
Complete one-liner you can invoke from within Visual Studio
In your solution root folder create a file called "CleanBin.bat" and add the following one-liner:
Powershell.exe -ExecutionPolicy Bypass -NoExit -Command "Get-ChildItem -inc bin,obj -rec | Remove-Item -rec -force"
Run the .bat file. Enjoy.
Original creds to the answer here: https://stackoverflow.com/a/43267730/1402498
The original answer shows the powershell command, but I had a lot of trouble making it work smoothly on my system. I finally arrived at the one-liner above, which should work nicely for most folks.
Caveat:
Microsoft seems to be great at making Windows security cause stranger and stranger behavior. On my machine, when I run the script, all obj and bin folders are deleted but then reappear 2 seconds later! Running the script a second time causes permanent deletion. If anyone knows what would cause this behavior, please let me know a fix and I'll update the answer.
for visual studio 2022
you can use:
https://marketplace.visualstudio.com/items?itemName=MadsKristensen.CleanSolution
If you need to delete bin and obj folders from ALL of your projects...
Launch git Bash and enter the following command:
find . -iname "bin" -o -iname "obj" | xargs rm -rf
For C# projects, I recommend appending $(Configuration) to obj folder, so-as to avoid deleting nuget files which are stored on obj base directory.
<Target Name="CleanAndDelete" AfterTargets="Clean">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)$(Configuration)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
If you delete the nuget files, it can be problematic to recreate them. Moreover, I've never seen a case where "Restore NuGet Packages" fixes this issue after these files have been deleted.

Resources