System.Reflection.TargetInvocationException while accessing a webservice - c#

I'm getting this unhandled exception error:
An unhandled exception of type 'System.Reflection.TargetInvocationException' (Exception has been thrown by the target of an invocation) occurred in the 3rd line of bool variable in the following code of BackEndUtil.cs
public static bool iMigrateProcess(string inputXML, out string outputXML,object objWebClient, string webSessionID)
{
outputXML = "";
object[] args = new Object[] { inputXML, outputXML };
bool bSuccess = (bool)objWebClient.GetType().InvokeMember("Process",
BindingFlags.Default | BindingFlags.InvokeMethod, null, objWebClient, args);
outputXML = (string)args[1];
return bSuccess;
}
Here is the process method from other file (reference.cs)
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://BackendWebService.domain/Process", RequestNamespace="http://BackendWebService.domain/", ResponseNamespace="http://BackendWebService.domain/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public string Process(string inputXML) {
object[] results = this.Invoke("Process", new object[] { inputXML });
return ((string)(results[0]));
}
Here I was consuming a web service (.asmx file) to stitch two image files. Here the inputXML seems to be fine containing XML of the file path of uploaded image file on server. However, the code doesn't go beyond line 3.
This code wasn't made by me so I have no idea how to troubleshoot this.
There are two InnerExceptions:
Make sure the file image is a valid managed assembly.
Make sure you have supplied a correct file path for the assembly.
Here is the code of iMigrateProcess from the Call Stack attached above.
public static bool iMigrateProcess(cDataContainer inputDC, out cDataContainer outputDC, object objWebClient)
{
return iMigrateProcess(inputDC, out outputDC, objWebClient, "");
}
public static bool iMigrateProcess(cDataContainer inputDC, out cDataContainer outputDC, object objWebClient, string webSessionID)
{
outputDC = null;
object[] args = new Object[] { inputDC, outputDC };
bool bSuccess = (bool)objWebClient.GetType().InvokeMember("Process",
BindingFlags.Default | BindingFlags.InvokeMethod, null, objWebClient, args);
outputDC = (cDataContainer)args[1];
return bSuccess;
}

Related

c# load dll from file, execute logic in dll, and use returned string

I am attempting to convert established code into a .dll which will be able to be loaded as required by the main program. The .dll does not require any input parameters from the main program and is intended to only return a string value. My primary resource has been this answer.
The dll code is structured:
namespace DLL
{
class DLLClass
{
public string PublicString(string OutputString)
{
// ... existing code ...
return OutputString;
}
}
}
The main program attempts to load the .dll, execute the logic, and retrieve the returned string for display in the console:
static void Main()
{
var DLLPath = new FileInfo("DLL.dll");
Assembly assembly = Assembly.LoadFile(DLLPath.FullName);
Type t = assembly.GetType("DLL.DLLClass");
object obj = Activator.CreateInstance(t);
MethodInfo method = t.GetMethod("PublicString");
string TargetString = (string)method.Invoke(obj, null);
Console.WriteLine("End of dll");
Console.WriteLine(TargetString);
Console.ReadLine();
}
This method presently fails as a TargetParameterCountException ("Parameter count mismatch") occurs at the .Invoke line. The debug information indicates the OutputString remains null at the time of the exception, meaning the code within the .dll does not appear to have run yet.
Thank you in advance for any assistance in this matter.
Change the below code
string TargetString = (string)method.Invoke(obj, null);
to
object[] parametersArray = new object[] { "Hello" };
string TargetString = (string)method.Invoke(obj, parametersArray);
You are not passing parameter value to the calling method so that it is having such issue.

Decrypt WebResource.axd URL generated on HTTPS instance

I have below mentioned code:
string urlEncodedData = URL.Text;
byte[] encryptedData = HttpServerUtility.UrlTokenDecode(urlEncodedData);
Type machineKeySection = typeof(System.Web.Configuration.MachineKeySection);
Type[] paramTypes = new Type[] { typeof(bool), typeof(byte[]), typeof(byte[]), typeof(int), typeof(int) };
MethodInfo encryptOrDecryptData = machineKeySection.GetMethod("EncryptOrDecryptData", BindingFlags.Static | BindingFlags.NonPublic, null, paramTypes, null);
try
{
byte[] decryptedData = (byte[])encryptOrDecryptData.Invoke(null, new object[] { false, encryptedData, null, 0, encryptedData.Length });
string decrypted = Encoding.UTF8.GetString(decryptedData);
decryptedLabel.BackColor = Color.Lime;
decryptedLabel.Text = decrypted;
}
catch (TargetInvocationException)
{
decryptedLabel.BackColor = Color.Red;
decryptedLabel.Text = "Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?";
}
It Decrypts and tell me details about webresource.
locally it works fine.
But on production it always gives me below message from catch block
Error decrypting data. Are you running your page on the same server and inside the same application as the web resource URL that was generated?
The only difference I have is production being on HTTPS. Is above code valid for HTTPS also, or do I have to make change(s) to it?
I also was using this code snippet to decrypt webresource.axd parameter, but lately it stopped working.
Maybe it's change of framework to 4.5, because I found this comment in .net sources - Page class, method DecryptString http://referencesource.microsoft.com/#System.Web/UI/Page.cs,18cf7b1fe99faea6
if (AspNetCryptoServiceProvider.Instance.IsDefaultProvider) {
// ASP.NET 4.5 Crypto DCR: Go through the new AspNetCryptoServiceProvider
// if we're configured to do so.
ICryptoService cryptoService = AspNetCryptoServiceProvider.Instance.GetCryptoService(purpose, CryptoServiceOptions.CacheableOutput);
clearData = cryptoService.Unprotect(protectedData);
}
else {
// If we're not configured to go through the new crypto routines,
// fall back to the standard MachineKey crypto routines.
#pragma warning disable 618 // calling obsolete methods
clearData = MachineKeySection.EncryptOrDecryptData(fEncrypt: false, buf: protectedData, modifier: null, start: 0, length: protectedData.Length, useValidationSymAlgo: false, useLegacyMode: false, ivType: IVType.Hash);
#pragma warning restore 618 // calling obsolete methods
}
Are you sure the only difference is http and https, maybe framework version also?
Nevertheless I used method DecryptString instead EncryptOrDecryptData and below code is working for me. You can check if this working for you too :)
private static string Decrypt(string webResourceParameter)
{
var purposeType = Type.GetType("System.Web.Security.Cryptography.Purpose, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
if (purposeType == null)
return null;
try
{
var purpose = Activator.CreateInstance(purposeType, "AssemblyResourceLoader.WebResourceUrl");
const BindingFlags decryptFlags = BindingFlags.NonPublic | BindingFlags.Static;
var decryptString = typeof (Page).GetMethod("DecryptString", decryptFlags);
var decrypt = decryptString.Invoke(null, new[] {webResourceParameter, purpose}) as string;
return decrypt;
}
catch (Exception ex)
{
return null;
}
}

Where to find the System.Net.Mail.MailWriter class? [duplicate]

So, the below code used to work in .NET 4 to get a System.Net.Mail.MailMessage object as a MemoryStream, however with the release of .NET 4.5 beta a runtime exception occurs.
Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
object mailWriter = mailWriterContructor.Invoke(new object[] { stream });
MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true }, null);
.....
}
Runtime exception occurs on sendMethod.Invoke().
Managed to figure out how to get this working again in .NET 4.5 beta. The private API Send() method in MailMessage has changed to: internal void Send(BaseWriter writer, bool sendEnvelope, bool allowUnicode)
Please find updated code below.
Assembly assembly = typeof(SmtpClient).Assembly;
Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter");
using (MemoryStream stream = new MemoryStream())
{
ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(Stream) }, null);
object mailWriter = mailWriterContructor.Invoke(new object[] { stream });
MethodInfo sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic);
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
.....
}
This might be usable if you don't want to go with unsupported hacks and don't mind extra performance hit.
public static class MailMessageExtensions
{
public static string RawMessage(this MailMessage m)
{
var smtpClient = new SmtpClient { DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory };
using (var tempDir = new TemporaryDirectory())
{
smtpClient.PickupDirectoryLocation = tempDir.DirectoryPath;
smtpClient.Send( m );
var emlFile = Directory.GetFiles( smtpClient.PickupDirectoryLocation ).FirstOrDefault();
if ( emlFile != null )
{
return File.ReadAllText( emlFile );
}
else
return null;
}
return null;
}
}
class TemporaryDirectory : IDisposable
{
public TemporaryDirectory()
{
DirectoryPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
Directory.CreateDirectory( DirectoryPath );
}
public string DirectoryPath { get; private set; }
public void Dispose()
{
if ( Directory.Exists( DirectoryPath ) )
Directory.Delete( DirectoryPath, true );
}
}
for checking if extra boolean i use :
If _sendMethod.GetParameters.Length = 2 Then
_sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Object() {_mailWriter, True}, Nothing)
Else
_sendMethod.Invoke(Message, BindingFlags.Instance Or BindingFlags.NonPublic, Nothing, New Object() {_mailWriter, True, True}, Nothing)
End If
The proposed solution with the extra TRUE works beautifully.
I started to getting the error while running my project in VS2012 even though I am not using .net 4.5 but 4.0 in all my libraries.
The error only happens on the machine where you have installed VS2012, looks like VS2012 makes reference to .net 4.5 while you are debugging. When you deploy and run the application in clients running .net 4.0 everything works fine.
Thus : If you run 4.0 - do not add the extra TRUE, if you run 4.5 add it.
We fought with the mail message conversion for a long time. Ultimately the solution was to use MimeKit.
var memoryStream = new MemoryStream();
var mimeMessage = MimeMessage.CreateFromMailMessage(message);
mimeMessage.WriteTo(memoryStream);
If you use the methods above you will get really close and it will work in most cultures but eventually the subject encoding will defeat you.
For those, who are struggling with mailWriterContructor being null in .NET 5 or facing Parameter count mismatch exception, take a closer look on my solution usable for any stream. Link here

Error when I use Open Office API in ASP .NET

I use an Open Office API in my ASP .NET application for reading text content from *.doc files.
public static bool getTextV2(string siteURL, string[] search)
{
//Create a new ServiceManager Type object
Type tServiceManager = Type.GetTypeFromProgID("com.sun.star.ServiceManager", true);
//Create a new ServiceManager Com object using our
//ServiceManager type object
object oServiceManager = System.Activator.CreateInstance(tServiceManager);
//Create our Desktop Com object
object oDesktop = Invoke(oServiceManager, "createinstance",
BindingFlags.InvokeMethod,
"com.sun.star.frame.Desktop");
//Create an array for our load parameter
Object[] arg = new Object[4];
arg[0] = siteURL;
arg[1] = "_blank";
arg[2] = 0;
arg[3] = new Object[] { };
//Create our new blank document
object oComponent = Invoke(oDesktop,
"loadComponentFromUrl",
BindingFlags.InvokeMethod,
arg
);
//Create an empty array for the getText method
arg = new Object[0];
//Get our Text Com object
Object oText = Invoke(oComponent,
"getText",
BindingFlags.InvokeMethod,
arg
);
Object Text = Invoke(oText,
"getString",
BindingFlags.InvokeMethod,
arg
);
string content = Text.ToString();
content = content.ToLower();
bool flag = true;
foreach (string current in search)
{
if (!content.Contains(current)) flag = false;
}
arg = new Object[0];
Invoke(oComponent,
"dispose",
BindingFlags.InvokeMethod,
arg
);
return flag;
}
public static object Invoke(object obj, string method, BindingFlags binding, params object[] par)
{
return obj.GetType().InvokeMember(method, binding, null, obj, par);
}
But I have the following error:
Retrieving the COM class factory for component with CLSID {82154420-0FBF-11D4-8313-005004526AB4} failed due to the following error: 80080005.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Runtime.InteropServices.COMException: Retrieving the COM class factory for component with CLSID {82154420-0FBF-11D4-8313-005004526AB4} failed due to the following error: 80080005.
Source Error:
Line 56: //Create a new ServiceManager Com object using our
Line 57: //ServiceManager type object
Line 58: object oServiceManager = System.Activator.CreateInstance(tServiceManager);
Line 59: //Create our Desktop Com object
Line 60: object oDesktop = Invoke(oServiceManager, "createinstance",
So, there is a error at line 58.
Any ideas?
Quick guess: could it be that user under which your are running app never opened OpenOffice before. Try login as that user and run OpenOffice it will ask few questions, then close OpenOffice and logout. Then try to run your app again....

Automate open and save OpenOffice Impress format as html/jpeg using C# reflection, or perl

I want to convert an OpenOffice Impress Presentation file and convert it to HTML or JPEG.
I have found a few examples, but they appear to be broken. I would like to do it, in a way that it does not matter what version of OpenOffice is installed, and I do not want to bundle any interop dlls with my application. Therefore, I am looking for a solution that is done in C# reflection, preferably, or Perl using Win32-OLE.
Also, how would you hide the OpenOffice GUI?
Check out this solution . There might need some changes on the declaration of the PropertyValues
public void Conversion(string sourcefile, string exportfile)
{
Type tServiceManager = Type.GetTypeFromProgID("com.sun.star.ServiceManager", true);
object oServiceManager = System.Activator.CreateInstance(tServiceManager);
object oDesktop = Invoke(oServiceManager,"createinstance",BindingFlags.InvokeMethod,"com.sun.star.frame.Desktop");
//Load Document
Object[] arg = new Object[4];
arg[0] = PathConverter(sourcefile); // or "private:factory/swriter" for a blank Document
arg[1] = "_blank";
arg[2] = 0;
object loadproperty1 = CreatePropertyValue("Hidden", true); // Executes the OpenOffice without UI
arg[3] = new Object[] { loadproperty1};
object oComponent = Invoke(oDesktop,"loadComponentFromUrl",BindingFlags.InvokeMethod,arg);
//Create an array for the storeToUrl method
arg = new Object[2];
arg[0] = PathConverter(exportfile);
object storeproperty1 = CreatePropertyValue("Overwrite", true); // Overrites if file exits and prevents errors
object storeproperty2 = CreatePropertyValue("FilterName", "HTML (StarWriter)"); // Export to HTML
arg[1] = new Object[] { storeproperty1,storeproperty2 };
Invoke(oComponent,"storeToUrl",BindingFlags.InvokeMethod,arg);
}
I published a previous solution regarding the exportformats and the string you need to pass
Helper Methods:
private static object CreatePropertyValue(object serviceManager,string name, object value)
{
object propertyvalue = Invoke(serviceManager, "Bridge_GetStruct", BindingFlags.CreateInstance|BindingFlags.InvokeMethod|BindingFlags.GetProperty,
"com.sun.star.beans.PropertyValue");
Invoke(propertyvalue, "Name", BindingFlags.SetProperty, name);
Invoke(propertyvalue, "Value", BindingFlags.SetProperty, value);
return propertyvalue;
}
private static object Invoke(object obj, string method, BindingFlags binding, params object[] par)
{
return obj.GetType().InvokeMember(method, binding, null, obj, par);
}
/// Convert into OO file format
/// The file.
/// The converted file
private static string PathConverter( string file)
{
try
{
file = file.Replace(#"\", "/");
return "file:///"+file;
}
catch (System.Exception ex)
{
throw ex;
}
}
Use OpenOffice::OODoc, it understands the XML format of OpenOffice documents, requires no openoffice binaries to be running or even to have openoffice installed.

Categories

Resources