How to convert IPictureDisp to System.Drawing.Image - c#

From a COM library (Microsoft Office Document Imaging aka MODI) I receive an image as an IPictureDisp which I would like to convert to a System.Drawing.Image object.
What would be the best way to do that?
Currently I'm using the code below, which however throws an NotImplementedException.
internal sealed class IPictureDispHost : AxHost
{
/// <summary>
/// Default Constructor, required by the framework.
/// </summary>
private IPictureDispHost() : base(string.Empty) { }
/// <summary>
/// Convert the image to an ipicturedisp.
/// </summary>
/// <param name="image">The image instance</param>
/// <returns>The picture dispatch object.</returns>
public new static object GetIPictureDispFromPicture(Image image)
{
return AxHost.GetIPictureDispFromPicture(image);
}
/// <summary>
/// Convert the dispatch interface into an image object.
/// </summary>
/// <param name="picture">The picture interface</param>
/// <returns>An image instance.</returns>
public new static Image GetPictureFromIPicture(object picture)
{
return AxHost.GetPictureFromIPicture(picture);
}
}
...
// somewhere later the conversion gets called
Image image = IPictureDispHost.GetPictureFromIPicture(picture);
This is the exception stack trace:
System.NotImplementedException: The method or operation is not implemented.
at System.Windows.Forms.UnsafeNativeMethods.IPicture.GetHandle()
at System.Windows.Forms.AxHost.GetPictureFromIPicture(Object picture)
at DocumentViewer.IPictureDispHost.GetPictureFromIPicture(Object picture)
I have references to stdole, System.Windows.Forms and System.Drawing in my project. Am I missing something?

Check out this article.
It describes three different options to take, just pick the one you find easiest or "cleanest" for your purposes (including the one you claim not to be working for you).
Olivier Jacot-Descombes: The link above is broken. I've added the corresponding link from the Internet Archive WayBackMachine:
Converting between IPictureDisp and System.Drawing.Image (MSDN Blogs > Andrew Whitechapel).

As it seems the picture obtained from the Microsoft Office Document Imaging COM components is not a valid IPictureDisp object and there seems no way to convert it.

Function GetImage(MyIPicture As stdole.IPictureDisp) As Drawing.Image
If CType(MyIPicture.Type, Integer) <> 1 then Throw New ArgumentException("Image not supported")
Return Drawing.Image.FromHbitmap(MyIPicture.Handle, MyIPicture.hPal)
End Function
Inspired from this post in the MSDN Forum.
No idea why the CType(MyIPicture.Type, Integer) = 1 is required, but it works..

Have you tried:
picture1.image = Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage(pict)

Microsoft.VisualBasic.Compatibility.VB6.Support.IPictureDispToImage is not guaranteed to always be included in future updates. So... taking the example from http://support.microsoft.com/kb/555417 I came up with the following
Example
Public Class ImageToPictureDispConverter
Inherits System.Windows.Forms.AxHost
Public Sub New()
MyBase.New("{63109182-966B-4e3c-A8B2-8BC4A88D221C}")
End Sub
Public Function GetImageFromIPictureDisp(ByVal objImage As stdole.IPictureDisp) As System.Drawing.Image
Dim objPicture As System.Drawing.Image
objPicture = CType(MyBase.GetPictureFromIPicture(objImage), System.Drawing.Image)
Return objPicture
End Function
End Class
I see in your constructor that you pass an empty string. I ended up having to pass the following string "{63109182-966B-4e3c-A8B2-8BC4A88D221C}". If I passed an empty string I received a system.formatexception error. It looks like you have everything I have except for this string in your call to base.
Hope this helps.

Related

IOC / Injecting StreamReader, StreamWriter Dependencies

I'm looking to learn how to correctly inject dependencies that come from the .NET Core library like StreamReader and FileStream. How do I inject these?
I have a class that reads in a file with a bunch of demographic census data, selects a random sampling of it, and then returns it as multiline string to its caller. It news up a FileStream to get access to a file's contents and then news up a StreamReader to read in the FileStream contents so I can manipulate the text. However, I'm looking to make this unit testable. If I needed to inject a class I created myself I'd generate an interface for the class to implement and pass that into the constructor, but this is a .NET Core type and there's no IFileStream, IStreamWriter, etc that I can inject. What would be the correct way to inject these so I can substitute in mocks during unit testing?
namespace MyNS.Lib
{
using System.IO;
using System.Text;
using PgpCore;
/// <summary>
/// A class for PGP encrypting strings.
/// </summary>
public class EncryptUtility
{
/// <summary>
/// Initializes a new instance of the <see cref="EncryptUtility"/> class.
/// </summary>
/// <param name="sampler">The CensusSampler needed by the class.</param>
public EncryptUtility(CensusSampler sampler)
{
Sampler = sampler;
}
/// <summary>
/// Encrypts a census file.
/// </summary>
/// <param name="censusFilePath">The path to the census file.</param>
/// <param name="keyPath">The path to the public key file.</param>
/// <returns>Returns an encrypted census file.</returns>
public string EncryptCensus(string censusFilePath, string keyPath)
{
using (FileStream census = new FileStream(censusFilePath, FileMode.Open))
{
var censusSr = new StreamReader(census);
var censusText = censusSr.ReadToEnd();
return EncryptString(censusText, keyPath);
}
}
}
}
I think what #devNull said probably makes the most sense. By encapsulating the portions of code that rely on things that don't make sense to inject and mock, I have kind of already separated out the parts of my code that need testing from parts that rely on the .NET Core runtime. I don't really need to test EncryptCensus because the only thing I'd be testing is that StreamReader works, which seems unnecessary. So I'll just test EncryptString. Thanks!

RazorEngine: Razor.Parse throws FileNotFoundException every once in a while

I'm having an issue with RazorEngine (version 3.4.1.0).
I'm using Razor.Parse method with very simple template in a service that fires up every few minutes, and it works without any issues most of the times, but every now and then it throws this exception on me:
System.IO.FileNotFoundException:
Could not find file 'C:\Users\username\AppData\Local\Temp\cw3sv4yk.dll'.
File name: 'C:\Users\username\AppData\Local\Temp\cw3sv4yk.dll'
(cw3sv4yk is a randomly generated name)
Has anyone bumped into this issue before, and if so - any hints to what the solution would be?
Thanks,
Przemek
EDIT:
I've just noticed that I'm also getting this exception occasionally:
RazorEngine.Templating.TemplateCompilationException: Unable to compile
template. Metadata file
'c:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll'
could not be opened -- 'The process cannot access the file because it
is being used by another process.'\n\nOther compilation errors may
have occurred. Check the Errors property for more information.
EDIT_2:
One more exception that's being thrown every now and then:
System.ArgumentException: Class name is required
Using an overloaded version of Razor.Parse method which caches templates solved the issue for us:
/// <summary>
/// Parses and returns the result of the specified string template.
/// </summary>
/// <typeparam name="T">The model type.</typeparam>
/// <param name="razorTemplate">The string template.</param>
/// <param name="model">The model instance.</param>
/// <param name="cacheName">The name of the template type in the cache or NULL if no caching is desired.</param>
/// <returns>The string result of the template.</returns>
public static string Parse<T>(string razorTemplate, T model, string cacheName)

MissingMethodException Plugin CRM2011

I found a couple of suggestions on this question but I can't get it on my problem.
We got a .ddl which replaces placeholders in a word file and returned a memorystream. This works fine in a deliverd Test Application with a WPF FrontEnd.
Now we need this solution in a CRM2011 context. I added a reference to this .dll file in my CRM Project, build the logic exactly the way as seen in the example and boom a MissingMethodException appears.
I debuged to the point where the Exception is thrown and found somethine like this:
readonly Dictionary<Type, object> typeMap = new Dictionary<Type, object>();
/// <summary>
/// Returns an instance of the DataService implementing the <typeparamref name="TService"/> interface
/// </summary>
/// <typeparam name="TService">type of the interface for the DataService</typeparam>
/// <returns></returns>
public TService For<TService>()
{
if (typeMap.ContainsKey(typeof(TService)))
{
object value = typeMap[typeof(TService)];
if (value is Type)
{
return (TService)Activator.CreateInstance((Type)typeMap[typeof(TService)]);
}
return (TService)value;
}
return Activator.CreateInstance<TService>();
}
The line Activator.CreateInstance(); throws the Exception. I have absolutely no idea what is going wrong here and why this piece of code works fine on the test app.
I'm assuming it's because you are either attempting to create a Static class, or a class without an empty constructor. Add try catch that displays the type that is attempting to be created to narrow down what is happening.

Why are my code blocks not rendering in the Sandcastle Help File?

I'm using the current version of Sandcastle from Codeplex that is integrated with VS.NET 2012 to build a .cmh help file. The help file is being created, but I can't seem to ever get any of my <code> blocks to emit in the help file. I have the following easy example I keep working with:
/// <summary>
/// This is the summary
/// </summary>
/// <code>var s;</code>
public string SomeValue { get; set; }
When I look at the output .chm file, the var s; code is not present anywhere. I have done the following:
Added reference to Code Block Component in the Sandcastle project properties.
Tried making tag <code lang="C#">var s;</code> and <code language="C#">var s;</code> but neither made a difference.
Read documentation on the following sites detailing this process but to no avail:
https://www.simple-talk.com/dotnet/.net-tools/taming-sandcastle-a-.net-programmers-guide-to-documenting-your-code/
http://www.ewoodruff.us/shfbdocs/
The example is obviously a simplified version, but I'm just trying to get the basics work here. What am I doing incorrectly or missing?
I don't think the code tag is allowed to be by itself, try putting it inside an <example> tag, like <example><code>var s;</code></example>. So this should work:
/// <summary>
/// This is the summary
/// </summary>
/// <example>
/// <code>var s;</code>
/// </example>
public string SomeValue { get; set; }

Accessing functions between two .csproj files in the same application

I incorporated a WLAN API given from Codeplex's Managed WiFi site into my C# project (Windows Form Application). In the API, different functions are given to retrieve various aspects of the machine's current WiFi profile. I am only interested in retrieving the RSSI strength given in the function below. I then want to take that value and stick it in a text box on my form.
(Visual Studio 2008)
In WlanAPI.cs file, the function I am interested in exists as such:
namespace NativeWifi
{
public class WlanClient
{
/// <summary>
/// Represents a Wifi network interface.
/// </summary>
public class WlanInterface
{
/// <summary>
/// Gets the RSSI.
/// </summary>
/// <value>The RSSI.</value>
/// <remarks>Not supported on Windows XP SP2.</remarks>
public int RSSI
{
get
{
return GetInterfaceInt(Wlan.WlanIntfOpcode.RSSI);
}
}
In myApp.cs I have a textbox simply named 'wifi' that will display the current RSSI.
I have included : 'using NativeWifi' in myApp.cs header, but can't seem to get the data from the RSSI function in the WlanAPI.csproj. The project builds and compiles just fine. I'm just snagged on getting the RSSI value.
In myApp.cs I have a statement to the effect of:
wifi.Text = (GetInterfaceInt(Wlan.WlanIntfOpcode.RSSI)); //app form txt_box=RSSI value
I know this is incorrect, but shows what I am trying to do.
Any ideas?
Thanks.
You should be able to solve the problems you are facing by
Adding a reference to WlanAPI.dll or WlanAPI project (if you add it to your solution)
Using code like following:
Using NativeWifi;
Class MyAPP : Form
{
public void PrintRSSI()
{
WlanClient client = new WlanClient();
var interfaces = client.Interfaces;
//Now chose an interface out of all the available interfaces. Usually there would be zero or 1 interfaces available
if(interfaces.Length > 0)
{
//Select first available interface. A more complicated logic can present the list of available interfaces to the user and and then display RSSI for the selected interface
wifi.Text = interfaces[0].RSSI.ToString();
}
}
//Other code for the class
}

Categories

Resources