Embedding DLL in a compiled C# executable - c#

I am using scitersharp with WinForms and trying to build a single standalone compiled c# executable. It's a simple "Hello World" app which loads an HTML file. Initially after compilation 3 DLLs (sciter.dll, sciter64.dll and SciterSharpWindows.dll) were being generated in the bin\Debug folder. So, i googled and tried to find a solution to embed those dll files into the executable. Here is what i tried:
Loading the DLL in project window in visual studio and setting the build option as "Embedded resource"
Add references to the resources but this method didn't worked and it's giving me the following error:
`A reference to resource 'pathto\sciter.dll' could not be added. Please make sure the file is accesible and that it is a valid assembly or COM component`
Read the solutions from this stackoverflow question
Installed Cosutra.Fody package and rebuild the project. This time i managed to embed only the SciterSharpWindows.dll
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Sciter;
using SciterSharp;
using SciterSharp.WinForms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
// Create a class-accesible sciter control
private SciterControl SciterElement;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Create a new instance of the sciter control
SciterElement = new SciterControl();
// Set the callback once the element is ready to be used
SciterElement.HandleCreated += SciterControl1_HandleCreated;
// Add the Sciter Control to the Form and fill it
this.Controls.Add(SciterElement);
SciterElement.Dock = DockStyle.Fill;
}
private void SciterControl1_HandleCreated(object sender, EventArgs e)
{
// Initialize with some HTML
SciterElement.SciterWnd.LoadHtml(#"
<div style='padding: 0px 8px;'>
<h1>
Hello World
</h1>
</div>
");
}
}
}
Is there any way to embed these resources into the executable? Also, please let me know if i am missing something? Thank you in advance.

Here is a workaround maybe you can refer to.
First, add the dll to Reference and set Copy Local to False.
Then create a new project folder "libs", copy the referenced dll into this folder, and set Build Action to "Embedded Resources"
In the main() method, add code to handle the exception "dll not found".
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs e)
{
//The namespace of the project is embeddll, and the embedded dll resources are in the libs folder, so the namespace used here is: embeddll.libs.
string _resName = "embeddll.libs." + new AssemblyName(e.Name).Name + ".dll";
using (var _stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(_resName))
{
byte[] _data = new byte[_stream.Length];
_stream.Read(_data, 0, _data.Length);
return Assembly.Load(_data);
}
}

Related

Run time Error when Application.SetCompatibleTextRenderingDefault(false); is set

Trying to convert from a Console app to a Winform app. The following Winform code compiles fine, but at runtime I'm getting the following error. I went through various solutions of similar errors online, but was still a bit confused. Maybe, someone here can help for my following specific code:
NOTE: It's probably not relevant for the question of this post. But just in case: I'm referencing micaut 1.0 Type Library in my VS2017 project that is needed for the code below.
Error [on Winform]:
SetCompatibleTextRenderingDefault must be called before the first IWin32Window object is created in the application.
Code from Console app:
using System;
using System.Windows.Forms;
using micautLib;
namespace MathInputPanel
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
MathInputControl ctrl = new MathInputControlClass();
ctrl.EnableExtendedButtons(true);
ctrl.Show();
ctrl.Close += () => Application.ExitThread();
Application.Run();
}
}
}
An attempt to convert the above code to Winform app [that gives the error]:
using System;
using System.Windows.Forms;
using micautLib;
private void button1_Click(object sender, EventArgs e)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false); //error occurs here
MathInputControl ctrl = new MathInputControl();
ctrl.EnableExtendedButtons(true);
ctrl.Show();
ctrl.Close += () => Application.ExitThread();
Application.Run();
}
As the error is trying to tell you, you can only call that function before you create the first form.
Move that to Main() (if it isn't already there).

How can the current barcode scan output the value?

I use a GD4430 handheld scanner from the company Datalogic with the included OPOS driver. With the following code I manage to address the scanner. When I start the program, the scanner becomes active and you can scan. But I can not display the results in a TextBox.
Does anyone see where the error lies?
Visual Studio 2010 C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace TestRead
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
axOPOSScanner1.BeginInit();
axOPOSScanner1.Open("USBHHScanner");
axOPOSScanner1.ClaimDevice(0);
axOPOSScanner1.DeviceEnabled = true;
axOPOSScanner1.DataEventEnabled = true;
axOPOSScanner1.PowerNotify = 1; //(OPOS_PN_ENABLED);
axOPOSScanner1.DecodeData = true;
}
void axOPOSScanner1_DataEvent(object sender, AxOposScanner_CCO._IOPOSScannerEvents_DataEventEvent e)
{
textBox1.Text = axOPOSScanner1.ScanDataLabel;
textBox2.Text = axOPOSScanner1.ScanData.ToString();
axOPOSScanner1.DataEventEnabled = true;
axOPOSScanner1.DataEventEnabled = true;
}
}
}
Was not the processing of AxOPOSScanner1.BeginInit() on the source originally in Form1.Designer.cs instead of here?
(I am assuming that the source file name is Form1.cs)
As below(in Form1.Designer.cs):
this.axOPOSScanner1 = new AxOposScanner_CCO.AxOPOSScanner();
((System.ComponentModel.ISupportInitialize)(this.axOPOSScanner1)).BeginInit();
this.SuspendLayout();
There is a possibility that the problem has occurred because you moved it to Form1.cs or calling BiginInit() on both Form1.Designer.cs and Form1.cs.
Or, the following processing does not exist in Form1.Designer.cs, or there is a possibility that the specified function name(axOPOSScanner1_DataEvent) is wrong.
this.axOPOSScanner1.DataEvent += new AxOposScanner_CCO._IOPOSScannerEvents_DataEventEventHandler(this.axOPOSScanner1_DataEvent);
In addition:
What you should do is to temporarily store the return value of all the methods, add a process to determine whether the method was executed normally, likewise It is to read the ResultCode property immediately after setting the property(possibly causing an error) and add processing to judge whether the property setting was done normally.
Also, although not related to DataEvent, PowerNotify setting must be done before DeviceEnabled = true.

Form freezing when loaded from a DLL that is imported at runtime in a console application

Continuing from my previous question: Trying to show a Windows Form using a DLL that is imported at the runtime in a console application
The form I am showing using the code given in the answer to my previous question by #Ksv3n is freezing (showing a wait cursor over it). For code please check out above link.
Try to use a BackgroundWorker, like this:
(I dind't compiled the code, this is an example for the approach)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
namespace DLLTest
{
class Program
{
static void Main(string[] args)
{
BackgroundWorker m_oWorker;
m_oWorker = new BackgroundWorker();
m_oWorker.DoWork += new DoWorkEventHandler(m_oWorker_DoWork);
m_oWorker.RunWorkerAsync();
Console.ReadLine();
}
static void m_oWorker_DoWork(object sender, DoWorkEventArgs e)
{
string DLLPath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + "\\TestLib.dll";
var DLL = Assembly.LoadFile(DLLPath);
foreach (Type type in DLL.GetExportedTypes())
{
dynamic c = Activator.CreateInstance(type);
c.test();
}
}
}
}
Online Resource:Background Worker for Beginners

Bitmap ArgumentException

I'm trying to create an example program and I'm having issues creating the Bitmap needed for it. When I try running the code below I'm getting an ArgumentException.
I think this is being thrown because it cannot find the file on the disk. If this is the case where do I put the file in my project so it can find it? I've tried putting the file in the main project directory and have tried placing it within the debug and release folders.
If this is not what is causing the issue can someone point me in the right direction?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Drawing;
namespace Given
{
public class Photo : Form
{
Image image;
public Photo()
{
image = new Bitmap("jug.jpg"); // ArgumentException thrown here
this.Text = "Lemonade";
this.Paint += new PaintEventHandler(Drawer);
}
public virtual void Drawer(Object source, PaintEventArgs e)
{
e.Graphics.DrawImage(image, 30, 20);
}
}
}
namespace Photo_Decorator
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Given.Photo());
}
}
}
It's throwing this because it can't find the JPG, and therefore can't create a proper bitmap object. You need to either place the image file in the same folder as the EXE (Debug? Release?), or specify the entire path to the image (e.g C:/jug.jpg). Hope this helps :)
You'd need to put the file in the same folder as the executable (bin\Debug or bin\Release). You could place it in the bin folder and just use #"..\jug.jpg" as the path instead so it worked in both Debug and Release modes.

VCF Vcard import c#

iam trying to write a class which imports *.vcf files (Vcard), because i didn´t found a adequate .net class to solve that job.
So i decided to treat the *.vcf file like a *.txt file. I just import the whole file, line by line, with a StreamReader. Finally i save the line into a List object.
The Code:
private List<string> vcardList = new List<String>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
using (StreamReader reader = new StreamReader(#"H:\VS.vcf"))
{
string line;
while ((line = reader.ReadLine()) != null)
{
vcardList.Add(line);
}
}
}
After importing the text i needed to edit the lines, because i need to remove all the unnecessary symbols.
I tried to use the RedEx claa:
private void button1_Click(object sender, EventArgs e)
{
vcardList[0] = Regex.Replace(vcardList[0], "BEGIN:", string.Empty);
}
that works very well, for the first line! but the *.vcf file is very complex and allways different.
So my question is: Is there a better way to solve that problem?
This is the *.vcf file:
BEGIN:VCARD
VERSION:2.1
N;LANGUAGE=de;CHARSET=Windows-1252:Test;Mustermann;;;(geschäftlich)
FN;CHARSET=Windows-1252:Test Mustermann (geschäftlich)
ORG:Mustermann CompanyTITLE;CHARSET=Windows-1252:CEO
TEL;WORK;VOICE:0049 1111 22 769 23 - 1
TEL;CELL;VOICE:0049 2222 33 71 55 90
ADR;WORK;PREF;CHARSET=Windows-1252:;;Frobuehl 22;Gothtown;;101092;England
LABEL;WORK;PREF;CHARSET=Windows-1252;ENCODING=QUOTED-PRINTABLE:Leihb=FChl 21=0D=0A=
101092 Frobuehl
X-MS-OL-DEFAULT-POSTAL-ADDRESS:2
URL;HOME:www.Test-Mustermann.de
EMAIL;PREF;INTERNET:Test#Test-Mustermann.de
X-MS-OL-DESIGN;CHARSET=utf-8:<card
END:VCARD
I only need the name and address. Thanks in advance
Pretty old, but it still works: https://github.com/drlongnecker/Thought.vCards
You can try to use this sample.
Helle, sry for the long delay.
I solved my problem now with the follwing code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Outlook.ContactItem contact;
Outlook.Application app = new Outlook.Application();
contact = (Outlook.ContactItem)app.Session.OpenSharedItem(#"C:\vv.vfc");
MessageBox.Show(contact.FirstName);
}
}
}
This is just an example of how to easily import a VCF file with C# . i hope this helps. Of course i wouldnt implement it in that way, i rather would create a method with a parameter "incomingFile" or smth else.
Berry
the solution with the outlook application is not effictive.
Outlook.Application app = new Outlook.Application();
this will open the outlook first. and actually you need only to open the vcard and parse it to extract the information you want from it.
C# purely does not has specific method or class for work with vcfs.
But these solutions can be way.last one is the best:
Work with Microsot.office.interop.outlook.
Ohhh nooo.it will open outlook first and then after steps you can do your work.surely its not best solution.
Use Thought vcard.its not too bad but image that you have multiple vcfs and you merge them in one vcf.with this package its too hard(or almost impossible) to work with it.
Use VCardlib .it doesnt has previous problem but its not update for work with vcf version4 until now.
I use MixERP.NET.VCard and its more simple and effective.

Categories

Resources