Message Properties File - vb.net

Is there a VB equivalent to org.springframework.context.support.ResourceBundleMessageSource package in java?
I am not focusing on Spring with this question. I want to know if there is a way to have a message properties file that I can pass variables like you can with hat java package.
Here is an example of what I would like to do.
In a properties file have the following line:
success.message = Successfully created document with Trans No. {0}
In source code have this line:
ResourceBundleMessageSource.getMessage("success.message",new String[] {transObject.getTransId()}, null));
This code uses the properties file finds success.message and passes the variable from getTransId().
I want to do this to centralize all my error messages. and not have hard coded messages throughout my code.
Is there some kind of equivalent in VB?

One solution is to use resource files. Add a resource by right clicking on the project and selecting project properties. Then click on resources, and add a new resource.
We work from the example in the question :
With resources we cannot follow the sam naming convention as you see above. We need to replace the '.' with a '_' ie: success.message -> success_message
Resource files do not allow the '.' in the key name.
Next we need to the message into the resource file.
"{0} successfully submitted the file."
We use {0}....{x} as place holders for variables.
The first line in the resource tab should look like this
success_message | {0} successfully submitted the file.
The function to do the replacing of the place holders should look like this:
Public Shared Function messageRetriver(ByVal message As String, ByVal variables As String()) As String
Dim i As Integer
Dim pattern As String
For i = 0 To variables.Length - 1
pattern = "\x7B" & i & "\x7D"
Dim myRegex As New Regex(pattern)
message = myRegex.Replace(message, variables(i))
Next
Return message
End Function
Now in your code all you have to do is call this function passing the resource, and the string array of variables.
Utility.messageRetriver(My.Resources.success_message, {"My Program"})
That should do the trick.
I used this as a resource to compile this information.

Related

Using a local image with EmbedBuilder

According to the Discord.NET documentation page for the EmbedBuilder class, the syntax (converted to VB) to add a local image to an EmbedBuilder object should look something like this:
Dim fileName = "image.png"
Dim embed = New EmbedBuilder() With {
.ImageUrl = $"attachment://{fileName}"
}.Build()
I'm trying to use something like this to add a dynamically created image to the EmbedBuilder, but I can't seem to get it to work properly. Here's basically what I've got:
Dim TweetBuilder As New Discord.EmbedBuilder
Dim DynamicImagePath As String = CreateDynamicImage()
Dim AttachURI As String = $"attachment:///" & DynamicImagePath.Replace("\", "/").Replace(" ", "%20")
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = AttachURI
End With
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendMessageAsync("THIS IS A TEST", False, Builder.Build)
My CreateDynamicImage method returns the full path to the locally created image (e.g., C:\Folder\Another Folder\image.png). I've done a fair amount of "fighting"/testing with this to get past the Url must be a well-formed URI exception I was initially getting because of the [SPACE] in the path.
MyClient is a Discord.WebSocket.SocketClient object set elsewhere.
The SendMessageAsync method does send the Embed to Discord on the correct channel, but without the embedded image.
If I instead send the image using the SendFileAsync method (like so):
MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(DynamicImagePath, "THIS IS A TEST", False, Builder.Build)
the image is sent, but as a part of the message, rather than included as a part of the Embed (this is expected behavior - I only bring it up b/c it was a part of my testing to ensure that there wasn't a problem with actually sending the image to Discord).
I've tried using the file:/// scheme instead of the attachment:/// scheme, but that results in the entire post never making it to Discord at all.
Additionally, I've tried setting the ImageUrl property to a Web resource (e.g., https://www.somesite.com/someimage.png) and the Embed looks exactly as expected with the image and everything when it successfully posts to Discord.
So, I'm just wondering at this point if I'm just missing something, or if I'm just doing it completely wrong?
I cross-posted this to issue #1609 in the Discord.Net GitHub project to get a better idea of what options are available for this and received a good explanation of the issue:
The Embed (and EmbedImage) objects don't do anything with files. They simply pass the URI as configured straight into Discord. Discord then expects a URI in the form attachment://filename.ext if you want to refer to an attached image.
What you need to do is use SendFileAsync with the embed. You have two options here:
Use SendFileAsync with the Stream stream, string filename overload. I think this makes it clear what you need to do: you provide a file stream (via File.OpenRead or similar) and a filename. The provided filename does not have to match any file on disk. > So, for example:
var embed = new EmbedBuilder()
.WithImageUrl("attachment://myimage.png")
.Build();
await channel.SendFileAsync(stream, "myimage.png", embed: embed);
Alternatively, you can use SendFileAsync with the string filePath overload. Internally, this gets a stream of the file at the path, and sets filename (as sent to Discord) to the last part of the path. So it's equivalent to:
using var stream = File.OpenRead(filePath);
var filename = Path.GetFileName(filePath);
await channel.SendFileAsync(stream, filename);
From here, you can see that if you want to use the string filePath overload, you need to set embed image URI to something like $"attachment://{Path.GetFileName(filePath)}", because the attachment filename must match the one sent to Discord.
I almost had it with my code above, but I misunderstood the intention and usage of the method and property. I guess I thought the .ImageUrl property somehow "automatically" initiated a Stream in the background. Additionally, I missed one very important piece:
As it's an async method, you must await (or whatever the VB.NET equivalent is) on SendFileAsync.
So, after making my calling method into an async method, my code now looks like this:
Private Async Sub TestMessageToDiscord()
Dim Builder As New Discord.EmbedBuilder
Dim AttachmentPath As String = CreateDynamicImage() '<-- Returns the full, local path to the created file
With Builder
.Description = "SAMPLE DESCRIPTION"
.ImageUrl = $"attachment://{IO.Path.GetFileName(AttachmentPath)}"
End With
Using AttachmentStream As IO.Stream = IO.File.OpenRead(AttachmentPath)
Await MyClient.GetGuild(ServerID).GetTextChannel(PostChannelID).SendFileAsync(AttachmentStream, IO.Path.GetFileName(AttachmentPath), "THIS IS A TEST", False, Builder.Build)
End Using
End Sub
Now, everything works exactly as expected and I didn't have to resort to uploading the image to a hosting site and using the new URL (I actually had that working before I got the response on GitHub. I'm sure that code won't go to waste).
EDIT
Okay, so I still ended up going back to my separately hosted image option for one reason: I have a separate event method that modifies the original Embed object during which I want to remove the image and replace the text. However, when that event fired, while the text was replaced, the image was "moved" to the body of the Discord message. While I may have been able to figure out how to get rid of the image entirely, I decided to "drop back and punt" since I had already worked out the hosted image solution.
I've tried everyting I could, but I got stuck at the same point at where you are now.
My guesses are that Discord doesn't like the embedded images from https://cdn.discordapp.com/attachments, and only accepts the new files from https://media.discordapp.net. I might be wrong though, this is the way it worked for me.
I believe it's only a visual glitch, as I found if you send a link for an image from cdn.discordapp.com/attchments in your regular Discord client, it bugs out and shows an empty embed for some reason.
That would make sense since the default link used in an embedded image actually starts with https://cdn.discordapp.com/attachments/...
You could solve this issue by using https://media.discordapp.net, but it seems like Discord.net is configured to use the old domain.

Accessing a resource by its path rather than its byte content - VB.NET

I'm writing a function which performs some operations from a DOCX file (building a custom TOC from it).
I'm a beginner in unit testing, and as far as I understand, it should be designed to check functionality independently.
I added a DOCX file as a resource in VS and configured it to be copied in the output directory.
The resource file is named testDOCXFile and can be accessed this way as an array of Bytes:
Dim content As My.Resources.testDOCXFile
The problem: the function I want to check requires a String describing the path to a given file.
Is there a "good-practice-compliant" way to get a path to this resource, without using string constants as shown below:
' Don't Repeat Yourself!
Dim contentPath = _
IO.Path.Combine(Assembly.GetExecutingAssembly().Location,
"Resources", "testFile.docx")

OpenFileDialog.InitialDirectory returns empty string instead of the path that opens in testing

I would like to point new users to the proper directory to where the file type may be found. However, I don't want to hamper the efficiency of experienced users, as there are more specific sub folders that they may wish to remain in throughout multiple file openings.
I found some context for openfileDialog for c++ here: Initial directory is not working for CFileDialog
However I am interested in a VB solution. Here is Microsoft's documentation:
https://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.initialdirectory(v=vs.110).aspx
in which they state
The InitialDirectory property is typically set using one of the following sources:
A path that was previously used in the program, perhaps retained from the last directory or file operation.
Here is my code:
If Not ImportDialog.InitialDirectory.Contains("Direct Access\Shell\Customer Invoices") Then
ImportDialog.InitialDirectory = "....\Direct Access\Shell\Customer Invoices\"
End If
How can I determine if a user would automatically be sent to this directory or a subdirectory in the tree if getting InitialDirectory is unreliable?
I saved the most recently opened folder and redirected the file path depending on if the user preferred a different path:
If _lastOpenFolder = "" Then
ImportDialog.InitialDirectory = "Direct Access\Shell\Customer Invoices\"
Else
ImportDialog.InitialDirectory = _lastOpenFolder
End If
If ImportDialog.ShowDialog = Windows.Forms.DialogResult.OK Then
_lastOpenFolder = ImportDialog.FileName.Substring(0, ImportDialog.FileName.LastIndexOf("\"))
_lastOpenFolder = _lastOpenFolder.Substring(0, _lastOpenFolder.LastIndexOf("\"))
End If

creating a folder and verifying that the path is ok

I want to create a folder in my VB .NET app but I can't get to verify that the path is correct. For example, if I enter
My.Computer.FileSystem.CreateDirectory("lol it will work")
It works... While it doesn't look like a folder path at all... How can I verify that the path entered is correct ? And since it doesn't throw any exception, the folder must be created somewhere, but where ? I can't find it...
Thank you
Your Directory name "lol it will work" is a valid name.
When you don't provide an explicit path, My.Computer.FileSystem.CreateDirectory() (as well as some other methods/functions) will assume the string you provided is the path to a directory which relative path is your Application's current directory.
So it doesn't matter whether you're passing a complete path (that looks like a valid folder path) or a partial path/folder name that will be associated with the application's Directory as long as :
the resolved Path is a valid path (that doesn't contains invalid chars or missing folder name separator)
you (your application) have access to that path
the resulting path doesn't exceed the max allowed number of characters.
you don't encounter some specific Exceptions...
So, how do you know your application current working path ?
Since you used My.Application.FileSystem :
My.Computer.FileSystem.CurrentDirectory ' Read/Write Property As String
You can use System.IO :
System.IO.Directory.GetCurrentDirectory() ' Get a String
System.IO.Directory.SetCurrentDirectory(NewPath) ' Set
You can also use System.Environment.Directory
Environment.CurrentDirectory ' Read/Write Property As String
Both three (My.Computer.FileSystem, System.IO.Directory and Environment) are writable, and returns the current directory to be resolved in case you're providing relative paths in your application.
So, to answer your question : "How can I verify that the path entered is correct ?"
If you just created the Directory and you get no exception, then the name of your (relative) directory is valid, and the directory has been created :
My.Computer.FileSystem.CreateDirectory("lol it will work")
' Verification :
If System.IO.Directory.Exists("lol it will work") Then
MessageBox.Show("The Directory has been created !")
Else
MessageBox.Show("The Directory has'n been created !")
End If
' Shows "The Directory has been created !"
So you know that even other Functions/Methods can resolve relative path (not all though) by fallbacking to the defined Relative Working Path of your Application.
The test above is the same as :
System.IO.Directory.Exists( _
Path.Combine(Environment.CurrentDirectory, "lol it will work"))
CAUTION :
Due to the writable nature of those objects, your application
may change the Current Directory any time.
Consider :
the use of alternative objects/variables to get your working directory or similar
working with only explicit paths
using a global/static variable that stores the CurrentDirectory upon startup (can fail very easily)
restoring the CurrentDirectory whenever you're changing it (though you will use at a time or another an object that changes the CurrentDirectory without warning - read the documentation of that object whenever it involves a directory manipulation; OpenFileDialog for example which has different behaviours on XP and Win7/8) - This move is the least recommended.
Alternates :
AppDomain.CurrentDomain
AppDomain.CurrentDomain.BaseDirectory
This is a ReadOnly Property. It returns the path to the directory your assembly (application) were loaded from. Caution ! This path has a trailing "\" like :
G:\Tools\...\Sources\bin\Debug\ ' <- !!!
Assembly.GetExecutingAssembly().Location
System.IO.Directory.GetParent(Assembly.GetExecutingAssembly().Location)
This will also return the path to the directory the assembly were loaded from, but without the trailing "\" due to the use of GetParent()
Using Assembly to retrieve a path is useful when you're dealing with dependencies where not all Assemblies are loaded from the same directory. Codes that uses relative paths should use this approach instead of the classic ones.
I assume the same applies for Thread Domain if you want to get deep in multithreads (while I'm not really sure of the relevant aspect of this assumption - Never used this one !) :
Thread.GetDomain().BaseDirectory ' ReadOnly
And the good old Application.StartupPath
Application.StartupPath ' ReadOnly
...which also has a trailing "\". You can't access StartupPath until the application has actually started ! However, I've never checked whether it's working well when you start another process from your application and using that through the other process... (if it's possible... just imagining though)

VB.NET-Trying to populate vss files in tree view

I am trying to replicate the tree style view in Source Safe into my application in vb.net... I have already added the COM objects and connected to Source Safe database successfully... What i need is the method to populate the tree view with Source Safe files.... The logic to populate it and other necessary info... Can anyone HELP me???
I have inserted the tree view in my form
I have added the COM object for source safe
I have connected to source safe 'srcsafe.ini' file for database connection
I know i can use recursive program to fetch all the files in source safe
The only problem is i don't know about source safe functions. I have tried the MSDN website and read about all the properties of source safe. But how i use them, need some example.
And about flags in source safe, what i need to do to those flags when i perform the source safe functions from my application .
And how can i make the user restrictions like in source safe to my application
]
Here is documentation on VSS Automation. I had another link but it appears to be broken now.
http://msdn.microsoft.com/en-us/library/bb509341(v=vs.80).aspx
To work with VSS you would first create an instance of the VSSDatabaseClass class and call its Open method:
Dim vssDatabase As String = "\\server\somepath\srcsafe.ini"
Dim ssdb As new VSSDatabaseClass()
ssdb.Open(vssDatabase, userName, password)
The two methods that you will use most often are get_VSSItem() and get_Items(). These will return a singile VSSItem (which is a file or project) or a collection of items. So to get the root project of the database, you would use code such as this:
Dim root As IVSSItem = ssdb.getVSSItem("$/", False)
The Type property of a VSSItem indicates if the item is a project or file. If it is a project, you can get its child items using get_Items:
If root.Type = 0 Then 'Type = 0 means it's a project
Dim items As IVSSItems = root.get_Items(False)
For Each item As IVSSItem In items
If item.Type = 0 Then
'item is a project
Else
'item is a file
End If
Next
End If
I hope this gets you started.