Build the destination path using Path.Combine() when the path is composited.
Many known System locations have a predefined value in Environment.SpecialFolder: in your case, Environment.SpecialFolder.Desktop
. Environment.GetFolderPath() accepts one of these values and returns the correct file system path.
This returns the Path of the Desktop folder for the current User:
Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
The Icon object has a Save() method that accepts a Stream as argument.
You can pass a FileStream to save the Icon to a File, preserving its format, or a MemoryStream, then use File.WriteAllBytes() to save the MemoryStream's buffer calling its ToArray()
method.
Using a Resource name, as a string, using ResourceManager.GetObject():
Dim iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "myIcon.ico")
Using stream As New FileStream(iconPath, FileMode.Create, FileAccess.Write, FileShare.None),
ico = TryCast(My.Resources.ResourceManager.GetObject("myIcon"), Icon)
ico?.Save(stream)
End Using
Or, depending on what fits better in the context of your operations:
Using stream As New FileStream(iconPath, FileMode.Create, FileAccess.Write, FileShare.None)
My.Resources.myIcon.Save(stream)
End Using
GC.Collect()
Note: here, I'm calling GC.Collect()
after calling Save()
directly on the Icon object generated by My.Resources
. The Docs don't exactly explain it: My.Resources
is a factory, it doesn't return the object stored in the Project's Resources, it generates a new object (a different one each time) from the data stored as a Resource. With My.Resources.myIcon.Save(stream)
, we create a new object, save its data to disc, but never actually dispose of it. Calling GC.Collect()
right after, the memory used is reclaimed immediately. If we don't, that memory is never reclaimed (we're leaking).
It's probably better to assign the generated object a to temporary variable declared with a Using
statement. The two methods that follow can make use of GC.Collect()
, calling it right after, to reclaim the allocated memory immediately, but it's not strictly required, we're not really leaking resources.
Open up Visual Studio's Diagnostic Tools
to test the behavior with and without GC.Collect()
, calling these methods multiple times.
Using stream As New FileStream(iconPath, FileMode.Create, FileAccess.Write, FileShare.None),
ico = My.Resources.myIcon
ico.Save(stream)
End Using
' GC.Collect() <= Not strictly required, but test the difference
Or using a MemoryStream:
Using ms As New MemoryStream(),
ico As Icon = My.Resources.myIcon
ico.Save(ms)
ms.Position = 0
File.WriteAllBytes(iconPath, ms.ToArray())
End Using
' GC.Collect() <= Not strictly required, but test the difference