Image.FromStream mono memory leak - memory-leaks

I believe I have stumbled across a memory leak in Mono 4.6 and 4.8 using the Image.FromStream call. Below is a code snippet that can be used to reproduce the problem. I have tested this in Ubuntu 16.04 LTS with Mono 4.6 and 4.8.
I have posted a Visual Studio/MonoDevelop solution and project (in a tar.gz file) here: BitmapTest.tar.gz. After extracting BitmapTest.gz, rename BitmapTest to BitmapTest.tar.gz so you can extract the code.
This project is a simple Winforms app that runs the code below.
Is there a work around, or something I am not considering?
EDIT:
If I use
using (Bitmap srcBitmap = (Bitmap)Image.FromFile(_file_name))
instead of
using (Bitmap srcBitmap = (Bitmap)Image.FromStream(ms))
It works. The problem seems to be in Image.FromStream.
// populate our byte[] array with a .BMP file
ImageConverter convert = new ImageConverter();
private byte[] _sourceArray = (byte[])convert.ConvertTo(Image.FromFile(filename_string), typeof(byte[]));
// put the following code in a loop
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(_sourceArray))
{
System.Diagnostics.Trace.WriteLine("First memory stream created OK size: " + ms.Capacity.ToString());
using (Bitmap srcBitmap = (Bitmap)Image.FromStream(ms))
{
System.Diagnostics.Trace.WriteLine("First Bitmap created OK size: " + srcBitmap.Size.ToString());
}
}
// If GC is called then the memory climbs slower
if (_forceGC) {
GC.WaitForPendingFinalizers();
GC.Collect();
}

Related

Java code OK in AIX 3.5, fails in RHEL 7.5: It makes corrupt DOC, DOCX, XLS, XLSX files but good HTML files

We have a Java process (see below) to generate DOC, DOCX, XLS, XLSX, and HTML and save it to our Linux PCs. It ran well in our old AIX 3.5 machine; but in our new RHEL 7.5 machine, Microsoft proprietary document formats (DOCX, DOC, XLSX, and XLS) it outputs are corrupt. HTML files are not corrupt.
I have downloaded the output files into a Windows PC and try to open them; Exception errors say the DOC/DOCX/XLS/XSLX files are corrupt and cannot be opened.
The Java code works well in the old Linux PC. I am assuming there might some libraries or software we need to install in the new PC.
Below is my java code (Process to generate the file)
int BUFFER_SIZE=1024*256;
int bytesRead=0;
Resultset rs=obj.resultSet();
DocumentClass = new DocumentClass();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream bis = new BufferedInputStream(rs.getBinaryStream(1));
try
{
bytesRead = bis.read(buffer,0,BUFFER_SIZE);
while (bytesRead > 0)
{
baos.write(buffer, 0, bytesRead);
buffer = new byte[BUFFER_SIZE];
bytesRead = bis.read(buffer,0,BUFFER_SIZE);
}
}
catch (IOException io )
{
System.out.println(io.getMessage());
}
DocumentClass.setFileBody(baos);
BufferedWriter CreateDoc = new BufferedWriter(new FileWriter("/usr/Test.docx"));
CreateDoc.write(DocumentClass.getFileBody().toString());
CreateDoc.close();

How to use LibvlcSharp on Linux?

I'm trying to use LibvlcSharp on a linux installation (Ubuntu 18.04). I'm following all the instructions, including this one Getting started on LibVLCSharp.Gtk for Linux but my application always crash. It's working perfectly on windows, because there we can add VideoLAN.LibVLC.Windows package, but I couldn't find someting similar for Linux.
My code:
static void Main(string[] args)
{
// Record in a file "record.ts" located in the bin folder next to the app
var currentDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
var destination = Path.Combine(currentDirectory, "record.ts");
// Load native libvlc library
Core.Initialize();
using (var libvlc = new LibVLC())
//var libvlc = "/usr/lib/x86_64-linux-gnu/";
using (var mediaPlayer = new MediaPlayer(libvlc))
{
// Redirect log output to the console
libvlc.Log += (sender, e) => Console.WriteLine($"[{e.Level}] {e.Module}:{e.Message}");
// Create new media with HLS link
var urlRadio = "http://transamerica.crossradio.com.br:9126/live.mp3";
var media = new Media(libvlc, urlRadio, FromType.FromLocation);
// Define stream output options.
// In this case stream to a file with the given path and play locally the stream while streaming it.
media.AddOption(":sout=#file{dst=" + destination + "}");
media.AddOption(":sout-keep");
// Start recording
mediaPlayer.Play(media);
Console.WriteLine($"Recording in {destination}");
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
The error message:
Unhandled Exception: LibVLCSharp.Shared.VLCException: Failed to perform instanciation on the native side. Make sure you installed the correct VideoLAN.LibVLC.[YourPlatform] package in your platform specific project
at LibVLCSharp.Shared.Internal..ctor(Func1 create, Action1 release)
at RadioRecorderLibVlcSharp.Program.Main(String[] args) in /media/RadioRecorderLibVlcSharp/Program.cs:line 19
Anyone can help me?
thanks
Can you try apt-get install vlc? That seems to help getting all the required plugins/deps on your system (though it will pull vlc 2.x from the official ubuntu rep probably).

Azure ARM uniqueString function mimic

I need to deploy Sql Databases into an Azure Sql Server using to ways: the ARM template way, and a more custom way using C# code. There's a ARM template function called uniqueString(string) that generate a pseudo random hash of a given string. It's a deterministic pure function.
I need to find a way to exactly mimic the behaviour of this function from my C# code. ie I need to reproduce this function into my C# code.
Where can i find the algorithm used by the ARM Api ?
MSDN reference for uniqueString()
Update 2023-01-05 - As suggested by other answers, there's an easier way now - just reference the Azure.Deployments.Expression nuget package which contains all of the Arm functions and then use the following convenience wrapper:
using Azure.Deployments.Expression.Expressions;
using Newtonsoft.Json.Linq;
public static class ArmFunctions
{
public static string? UniqueString(params string[] values)
{
var parameters = values.Select(
arg => new FunctionArgument(
JToken.FromObject(arg)
)
).ToArray();
var result = ExpressionBuiltInFunctions.Functions
.EvaluateFunction("uniqueString", parameters, null);
return result.Value<string>();
}
}
// "zcztcwvu6iyg6"
var unique = ArmFunctions.UniqueString("tyeth");
Original answer for posterity:
I've been researching this myself on and off for a few years now, and I've finally hit paydirt...
// "zcztcwvu6iyg6"
var unique = ArmUniqueString("tyeth");
My ArmUniqueString function is a wrapper around some dlls that are distributed with the Azure Stack Hub Development Kit which is basically a virtual machine image that contains the Azure server-side platform that you can run locally...
private static string ArmUniqueString(string originalString)
{
var assembly = Assembly.GetAssembly(
typeof(Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.Engines.TemplateEngine)
);
var functions = assembly.GetType(
"Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.Expressions.TemplateExpressionBuiltInFunctions"
);
var uniqueString = functions.GetMethod(
"UniqueString",
BindingFlags.Static | BindingFlags.NonPublic
);
var parameters = new object[] {
"uniqueString",
new JToken[] {
(JToken)originalString
}
};
var result = uniqueString.Invoke(null, parameters).ToString();
return result;
}
You'll need to download the Azure Stack Hub Development Kit and unpack it to get the dlls:
Download the Azure Stack Hub Development Kit - warning: it's about 22Gb!
Run the installer to unpack a 55Gb *.vhdx
Mount the *.vhdx, or expand / unpack it locally
Inside the *.vhdx, find this file and unzip it somewhere:
CloudBuilder\CloudDeployment\NuGetStore\Microsoft.AzureStack.Setup.Services.ResourceManager.5.20.1335.300.nupkg
The content\Website\bin folder inside the *.nupkg contains the necessary dlls
To use them, add an assembly reference to Microsoft.WindowsAzure.ResourceStack.Frontdoor.Templates.dll (it has some dependencies on other files in the bin folder) and that contains the TemplateExpressionBuiltInFunctions class. The code above just uses reflection to invoke the private UniqueString function from that assembly, with a little bit of work to marshal the parameters into appropriate JToken types.
If you wanted to dig into the implementation details you could probably run a decompiler against the assembly to find out what it's doing under the covers...
Note - credits go to this blog article for pointing me in the right direction:
https://the.agilesql.club/2017/12/azure-arm-template-function-internals/
I found some PowerShell code to do this here: https://blogs.technet.microsoft.com/389thoughts/2017/12/23/get-uniquestring-generate-unique-id-for-azure-deployments/
I converted this code to C#:
public string GetUniqueString(string id, int length = 13)
{
string result = "";
var buffer = System.Text.Encoding.UTF8.GetBytes(id);
var hashArray = new System.Security.Cryptography.SHA512Managed().ComputeHash(buffer);
for(int i = 1; i <= length; i++)
{
var b = hashArray[i];
var c = Convert.ToChar((b % 26) + (byte)'a');
result = result + c;
}
return result;
}
This function is released in nuget: https://www.nuget.org/packages/Azure.Deployments.Expression/
The implementation:
https://msazure.visualstudio.com/One/_git/AzureUX-Deployments?path=%2Fsrc%2FExpressions%2FExpressions%2FExpressionBuiltInFunctions.cs&version=GBmaster&_a=contents
Example:
using Azure.Deployments.Expression.Expressions;
using Newtonsoft.Json.Linq;
var funcs = ExpressionBuiltInFunctions.Functions;
var jt = new JTokenExpression("test");
var output = funcs.EvaluateFunction("uniqueString", new JToken[] { jt.Value }).ToString();
Sam Cogan wrote a blog post on how to do this in C# here: https://samcogan.com/using-bicep-functions-in-c-if-you-really-want-to/
Inspired by Sam, I wrote a PowerShell module (for PowerShell 7) that does the same. You can install the module by running Install-Module -Name AzExpression which will give you command called New-AzUniqueString.
Here is an example on how to use it:
New-AzUniqueString -InputStrings 'test', 'value'
Which will output: bhxq2thzm5dym
I finally found a workaround. I used a very simple ARM template which goal is to only output the result of the uniqueStringcommand. Then I fetch this output in my C# code. This solution is not really the quickest one ;-), but it works as desired.
Here is a bicep template which will output a uniqueString for a resource group:
output unique string = uniqueString(resourceGroup().id)

Playing wav/mp3 from Windows 7 service

I need to play a sound file (wav or mp3 is fine) from a service in Windows 7/2008... the way we did it in WinXP doesn't work anymore. I've followed this question Play wave file from a Windows Service (C#) with no success, in various combinations. The sound plays fine through the debugger but once I install it as a service it doesn't play, and event logs prove the call is being made. I've also followed the http://bresleveloper.blogspot.co.il/2012/06/c-service-play-sound-with-naudio.html link with the same result.
Code snippet follows below. It is a C# service with VS 2010, .Net 4.0, NAudio 1.5.4.0. I am using
InstallUtil to install/remove the service.
WRT the code, I comment out the Wav or MP3 stuff and one of the methods each time... they all play the sound sucessfully.
static class Program
{
[DllImport("kernel32.dll")]
public static extern Boolean AllocConsole();
static void Main(string[] args)
{
m_eventLog = new EventLog();
m_eventLog.Source = "EventLoggerSource";
if(args.Length > 0 && args[0].ToLower() == "/console")
{
AllocConsole();
EventLoggerApp app = new EventLoggerApp();
app.Start();
m_eventLog.WriteEntry("INFO (Calling Player)");
string fileFullPath=#"c:\aaasound\bunny_troubles.wav",fileFullPath2=#"c:\aaasound\dreams.mp3";
// Wav file
IWavePlayer wavePlayer=new WaveOutEvent(); // Method 1
IWavePlayer wavePlayer=new WasapiOut(NAudio.CoreAudioApi.AudioClientShareMode.Shared,false,100); // Method 2
AudioFileReader audioFile=new AudioFileReader(fileFullPath);
audioFile.Volume = (float)1.0;
wavePlayer.Init(audioFile);
// MP3 file
IWavePlayer wavePlayer=new WasapiOut(NAudio.CoreAudioApi.AudioClientShareMode.Shared,true,100); // Method 1- EventSync/not both work
IWavePlayer wavePlayer=new WasapiOut(NAudio.CoreAudioApi.AudioClientShareMode.Exclusive,false,100); // Method 2- EventSync must be false or throws an exception
WaveStream mp3Reader = new Mp3FileReader(fileFullPath2);
WaveChannel32 inputStream=new WaveChannel32(mp3Reader);
WaveStream wavStream=new WaveChannel32(inputStream);
wavePlayer.Init(wavStream);
//this.wavePlayer.PlaybackStopped += new EventHandler(wavePlayer_PlaybackStopped);
wavePlayer.Play();
while(wavePlayer.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(100);
}

Using HtmlAgilityPack with MonoTouch app gives reference error

I'm trying to use the Html Agility Pack with a MonoTouch application, but cannot find a version that will work with it.
I downloaded the latest binaries from CodePlex and I've tried building with every DLL it contains. None will compile when the target is the iPhone.
Adding the .NET 20 library will allow it to compile to the iPhone Simulator, but when switching to the iPhone I get the error:
Error MT2002: Can not resolve reference: System.Diagnostics.TraceListener (MT2002) (MFLPlatinum12)
It seems like others are using HtmlAgilityPack with MonoTouch projects, so any thoughts as to what I'm missing?
Are you compiling from source or using the DLL directly?
You will need to make a new MonoTouch library project and add all the files for it to work.
Using a DLL directly likely won't work, since it was not compiled for MonoTouch.
You have to compile it from code
Download the source
go into
\htmlagilitypack-99964\Branches\1.4.0\HtmlAgilityPack
Edit the csproj change to
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
Save and load
Fix errors
Trace -> Debug
Remove block
if (!SecurityManager.IsGranted(new DnsPermission(PermissionState.Unrestricted)))
{
//do something.... not at full trust
try
{
RegistryKey reg = Registry.ClassesRoot;
reg = reg.OpenSubKey(extension, false);
if (reg != null) contentType = (string)reg.GetValue("", def);
}
catch (Exception)
{
contentType = def;
}
}
Remove block
if (SecurityManager.IsGranted(new RegistryPermission(PermissionState.Unrestricted)))
{
try
{
RegistryKey reg = Registry.ClassesRoot;
reg = reg.OpenSubKey(#"MIME\Database\Content Type\" + contentType, false);
if (reg != null) ext = (string)reg.GetValue("Extension", def);
}
catch (Exception)
{
ext = def;
}
}
Use the dll in the bin/debug folder

Resources