I'm developing a custom MSBuild task by inheriting from the base Task class. My task calls the Copy task declared in Microsoft.Build.Tasks.dll setting the DestinationFolder property in the process. My custom task has a property called DestinationFolder declared as
public ITaskItem DestinationFolder { get; set; }
When calling this task from a build/project file I might pass in a parameter such as
<MyTask DestinationFolder="C:\Development\Test\%(RecursiveDir)"
the problem I have is that when this task executes, the DestinationFolder property seems to have no knowledge of the %(RecursiveDir) bit, instead just seems to be set to C:\Development\Test\Bin.
This question seems to suggest that there is no work-around for this problem. Is this definitely the case? I was wondering if it's possible to declare the property as a simple string then create a TaskItem object on the fly and if the DestinationFolder string contains the special %(RecursiveDir) instruction to then set up the TaskItem object accordingly.
The linked question deals with output parameters from a task, where this one deals with inputs. The problem here is that you've declared DestinationFolder as an ITaskItem, but you're passing in a string.
You haven't given enough of an example for me to figure out exactly what you're trying to do, but assuming you have a file called "C:\Development\Test\Bin\SomeFile.txt", you could define an item in your project like:
<ItemGroup>
<DestinationFolderArgument Include="C:\Development\Test\**\SomeFile.txt" />
</ItemGroup>
<MyTask DestinationFolder="#(DestinationFolderArgument)" />
Now your task will have access to all of the item's metadata, and RecursiveDir will contain "Bin\".
Related
We have a business rule built in VB that uses an MVC layout. We have need of certain variables throughout the different functions/subs at any given moment, so we made a class similar to this:
Public Class PublicVariables
Public Shared itemID As String
Public Shared FLD01 As String
Public Shared FLD02 As String
Public Shared FLD03 As String
Public Shared FLD04 As String
Public Shared FLD05 As String
Public Shared FLD06 As String
Public Shared FLD07 As String
Public Shared FLD08 As String
Public Shared FLD09 As String
Public Shared FLD10 As String
End Class
The problem is that if two people run this business rule at the same time, it appears that the public variables are being reused. For example, if one person triggers the rule under itemID ABC123 and a different person triggers the rule under itemID DEF456, the second person will actually be using the itemID ABC123 because the public variable for itemID still holds that value (even though it is running a different instance of the rule). I tried clearing all variables at the beginning of the code. I've also tried instantiating a new PublicVariables object at the beginning of the code and just reference the variables that way, but now I'm running into this issue when trying to go that route: https://learn.microsoft.com/en-us/dotnet/visual-basic/language-reference/error-messages/bc42025
Is there any way to get around this issue, but still have the ability to use the public variables?
I think you've just learned the hard way why use of global varaiables (e.g. Shared in a VB Class, or any variable in a VB Module) is generally discouraged. (https://wiki.c2.com/?GlobalVariablesAreBad, https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil, https://www.quora.com/Is-it-a-bad-practice-to-use-global-variables-in-any-programming-language)
Not sure you what mean by "public variables", but anyway this "PublicVariables" thing seems more like a context thing (The term "Context" in programming?). So yes, for starters, do remove the Shared keyword; after that, instantiating a new PublicVariables object might then bring progress. That BC42025 issue is a warning which will go away after the Shared gets dropped.
However, this seems like the start of some seriously needed refactoring, so good luck!
I have an implementation of CustomChange that I need access to the file name of the changeSet in which it is defined.
Any ideas? The CustomChangeWrapper has a reference to the ChangeSet that does have the value I need (changeSet.filePath) but is not passed as part of the CustomChange interface.
Looking at the source, I would try using the public SortedSet<String> getParams() and/or the public String getParamValue(String key) methods that are defined in CustomChangeWrapper
In the auto-generated resource designer file, there are properties for each resource. The property calls "GetString" which returns the string value. I would like to override this getstring function so I can do logic to see if I need to retrieve this value or a different value. I can't figure out how to do this because the designer file is auto-generated.
Public ReadOnly Property General() As String
Get
Return ResourceManager.GetString("General", resourceCulture)
End Get
End Property
For example, in my version of the GetString function, I would check the key passed in ("General") and see if there is a custom value for this key in a database. If the custom value exists, I would use that value. If the custom value does not exist, I would call the base GetString function to get the Resource value. I'd like to use the built in Resource class for this because then in my code I can just use "#Resources.General" and take advantage of the auto-complete functionality that already exists.
Refer to ASP.NET Resourcemanager to read local .resx. It's in C# but you can just convert it over. It isn't 100% of what you are looking for but shows a way of overriding in which you may be able to adjust to work with your needs.
I'm really struggling to get my head around the idea of working with a Class Library and I'm pretty much at the point of just maintaining separate projects with duplicate classes rather than a shared class library.
I've created a solution that contains a single class library project and two web applications. My main problems are the connection strings. These are held/declared in the web projects and I'm having to pass them into the class library every time I perform any kind of data access. I sort of understand why I should do this so I'm going with it for the moment.
This has now led me to a problem/question with lazy loading. I'm using lazy loading for the following property:
Public Property KeyRelationshipManager() As Employee
Get
If _keyRelationshipManager Is Nothing Then
_keyRelationshipManager = Employee.GetEmployee(_keyRelationshipManagerStaffNumber)
Return _keyRelationshipManager
Else
Return _keyRelationshipManager
End If
End Get
Set(ByVal value As AECOM.Employee)
_keyRelationshipManager = value
End Set
End Property
Because this property is using the function:
Employee.GetEmployee
I need to pass in the connection string to that function.
This means I would need to pass the connection string in to the property every time I use it so I could pass it into the function.
Is this correct? It doesn't 'feel' right to me because I'm going to have to adjust a huge number of functions and property and pass through the connections string.
Why are you passing the connection string in to the class library? Use ConfigurationManager.ConnectionStrings["myClassLibraryConnection"] in your class library. As long as you have that connection string in both your host applications' config files, it should be fine. It's the web.config files' jobs to bind the configuration of different class libraries to form a single application.
I have a Hashtable implementation (in class modules folder).
But I get a strange (long) error, for which no help is provided..
Error throws when I make the Function that return Hashtable Public.
It says:
"Private object modules cannot be used in public object modules as parameters or return types for public procedures (**this is what i need), as public data members, or as fields of public user defined types."
I need very simple logic. I want to be able to get a Function inside one Worksheet to performs some check, fill a Hashtable and return it so I can iterate in it in another Worksheet. Is this even possible (How I do it in C#)
Thanks in advance
The error means that you have your class Instancing property set to Private, which means that you can't use it anywhere where it might get used elsewhere. Mark it as PublicNotCreatable and your error will go away. I'm not clear on what exactly it is you're doing in your app, so that's the first thing to try.