Using An Array on Multiple Web Forms and within a DLL - c#

I have an input web form that will take in 45 user entered data, and then once the user has entered all data he/she can click a button that takes the 45 inputs, does a calculation via a DLL file, and then places all the output information on a different web form page. My question is how do I collect all the 45 input data, and place them into an array which both the DLL can access and the output form? I believe the back end of the dll is written in fortran and the original developer passed the visual basic array into the dll by using "ByRef ArrayInput As Double".

Since the original was Fortran you need to use standard calling convention. Try code like below :
class Program
{
[DllImport("MyDll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
private static extern uint CallWithDouble(IntPtr data);
static void Main(string[] args)
{
double[,] myDoubleArray = new double[9, 5];
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(myDoubleArray));
Marshal.StructureToPtr(myDoubleArray, ptr, true);
uint results = CallWithDouble(ptr);
}
}

Related

Send data to Excel file using DDE

I know DDE is old fashion outdated technology. But I am creating a C# Windows Form application to send data to Excel file for research purpose. I use Win32 DDE functions and below is what I have tried so far.
Pinvoke signatures:
[DllImport("user32.dll", EntryPoint = "DdeInitialize")]
public static extern int DdeInitialize(out uint pidInst, IntPtr pfnCallback, IntPtr afCmd, IntPtr ulRes);
[DllImport("user32.dll", EntryPoint = "DdeConnect")]
private static extern IntPtr DdeConnect(uint idInst, IntPtr hszService, IntPtr hszTopic, IntPtr pCC);
[DllImport("user32.dll", EntryPoint = "DdeCreateStringHandle")]
private static extern IntPtr DdeCreateStringHandle(uint idInst, string psz, int iCodePage);
public Form1()
{
InitializeComponent();
Process application = new Process();
application.StartInfo.FileName = #"C:\Users\xxx\Desktop\DDE_Client.xlsx";
application.Start();
uint instId;
DdeInitialize(out instId, application.MainWindowHandle, IntPtr.Zero, IntPtr.Zero);
IntPtr sPtr = DdeCreateStringHandle(instId, "Excel", 1004);
IntPtr tPtr = DdeCreateStringHandle(instId, "Sheet1", 1004);
IntPtr channel = DdeConnect(instId, sPtr, tPtr, (IntPtr)null);
}
DdeConnect returns non-zero value which indicates the connection is successful.
My question:
How to send a string value to the excel sheet? For example, I want to send "Name" to excel cell A1. Which DDE function should I use for the task?
You are trying to use DDEML and it is indeed hard to find decent DDEML examples because many people who actually needed to use DDE had done so directly using raw Windows Messages.
You will have to first start client transaction using DdeClientTransaction and then corresponding api like DdeGetData or DdeAddData, DdeAccessData etc to access or get the data.
You can find more details about DDEML in the MS Documentation here.
But since you are already using C# I highly recommend that it would be much better to just add a reference to the Microsoft Excel or Office Object Library in COM Assemblies section and use Microsoft.Office.Interop.Excel;
using Microsoft.Office.Interop.Excel;
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();

How To drag images directly from Camera or Smartphone to C# app?

I found a script (http://www.codeproject.com/Articles/28209/Outlook-Drag-and-Drop-in-C) that makes it possible to drag images to a c# application. (especially from outlook) The fileDrop format is used to copy (drag) images from my Hard disk to c# app.
This works well when the images are stored on my hard disk, but when i try to drag the images directly from my storage card (from Camera or smartphone (like a Samsung S3)) it won't work.
These are the drag formats i'm getting from those image(s):
(0): "Shell IDList Array"
(1): "FileContents"
(2): "FileGroupDescriptorW"
(3): "WPD Storage Attributes"
(4): "Preferred DropEffect"
(5): "WPD NSE"
(6): "WPD NSE PnPDevicePath"
(7): "WPD NSE StoragePUID"
(8): "UsingDefaultDragImage"
(9): "DragImageBits"
(10): "DragContext"
(11): "DragSourceHelperFlags"
(12): "InShellDragLoop"
(13): "IsShowingLayered"
(14): "DragWindow"
(15): "IsComputingImage"
(16): "DataObjectAttributes"
(17): "DisableDragText"
(18): "IsShowingText"
(19): "DropDescription"
(20): "ComputedDragImage"
(21): "Logical Performed DropEffect"
(22): "Performed DropEffect"
(23): "Paste Succeeded"
When i try to access the 'FileGroupDescriptorW' i'm receiving an Illegal access violation error. Also, 'FileGroupDescriptor' seems to be missing here?
Could anyone help me resolve this issue? I searched this site and Google, but didn't find anything useful.
The solution was posted by John Schroedl and was hidden in the many reactions on the Topic.
These two 'fixes' fixed my problem:
http://www.codeproject.com/Articles/28209/Outlook-Drag-and-Drop-in-C?msg=3535951#xx3535951xx
OLD C#:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class FILEGROUPDESCRIPTORA
{
public uint cItems;
public FILEDESCRIPTORA[] fgd;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public sealed class FILEGROUPDESCRIPTORW
{
public uint cItems;
public FILEDESCRIPTORW[] fgd;
}
FIXED C#:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public sealed class FILEGROUPDESCRIPTORA
{
public uint cItems;
public FILEDESCRIPTORA fgd;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public sealed class FILEGROUPDESCRIPTORW
{
public uint cItems;
public FILEDESCRIPTORW fgd;
}
And this fix: http://www.codeproject.com/Articles/28209/Outlook-Drag-and-Drop-in-C?msg=3551197#xx3551197xx
Old:
case "FileContents":
//override the default handling of FileContents which returns the
//contents of the first file as a memory stream and instead return
//a array of MemoryStreams containing the data to each file dropped
//get the array of filenames which lets us know how many file contents exist
string[] fileContentNames = (string[])this.GetData("FileGroupDescriptor");
Fix:
case "FileContents":
//override the default handling of FileContents which returns the
//contents of the first file as a memory stream and instead return
//a array of MemoryStreams containing the data to each file dropped
//
// FILECONTENTS requires a companion FILEGROUPDESCRIPTOR to be
// available so we bail out if we don't find one in the data object.
string fgdFormatName;
if (GetDataPresent("FileGroupDescriptorW"))
fgdFormatName = "FileGroupDescriptorW";
else if (GetDataPresent("FileGroupDescriptor"))
fgdFormatName = "FileGroupDescriptor";
else
return null;
//get the array of filenames which lets us know how many file contents exist
string[] fileContentNames = (string[])this.GetData(fgdFormatName);
In case anyone needs it...

c# dllimport wchar_t * to stringbuilder

what i have in hidapi.c library:
int HID_API_EXPORT HID_API_CALL testwchar(wchar_t * string) {
//...
wcsncpy(string, cur_dev->serial_number, wcslen(cur_dev->serial_number));
return wcslen(cur_dev->serial_number);
}
what i have in c#:
[DllImport("hidapi.dll", CharSet = CharSet.Unicode)]
public static extern unsafe int testwchar(StringBuilder stringt);
StringBuilder sb = new StringBuilder(64);
res = testwchar(sb);
i've missed some part of code in c function //... it enumerates devices and searches by vid/pid and returns serial, it works fine when i tested it in testapi.cpp, but when i've tryed to write c# gui...visual studio 2012 raises error talking about imbalanced stack... as i understand if i use string as out parameter i need to use stringbuilder instead of string.
what am i doing wrong? thanx for any advice.
p.s. sorry, but formatting doe not worked, so code is a mess...
I'd suggest using the hidapi functions yourself to compile the information you want. You can find documentation for them here, rather than using this string function. It'll be far more efficient.
If you need poniters, the code on this page should help you.

How to add an icon to an existing exe file (without an icon by default)?

When I was searching on Google I found a useful class which let us change the icon of any .exe file using the following line of code :
WindowsFormsApplication1.IconInjector.InjectIcon("myfile.exe", "myicon.ico", 200, 1);
Where 200 and 1 are respectively icon GroupID and icon BaseID which I can determine using Resource Hacker. In this case the file's icon changes successfully without corrupting the file.
So i planned to use this class on my program which is a SFX / Software protector, the output file always hasn't an icon, all what I can see on Resource hacker is the below :
i can't see icon group id nor the base id, anyway, (I don't know what to put instead of 200 and 1 in this case) So I tried to change the icon using the same line of code mentioned above, I used the following line of code (same as above):
WindowsFormsApplication1.IconInjector.InjectIcon("myfile.exe", "myicon.ico", 200, 1);
The file icon was successfully changed but the file doesn't work anymore!
When I tried to reopen the file using ResourceHacker, I found the below:
It seems that the icon resources were successfully added, but i can't figure out why the file doesn't work anymore, it seems that is corrupted.
Any help would be appreciated.
Note : I tried using this class with unprotected file and it works like a charm!
The class I am using is the below:
// IconInjector.cs
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace WindowsFormsApplication1
{
/// <summary>
/// IconInjectorクラスの定義
/// </summary>
public class IconInjector
{
[DllImport("kernel32.dll", SetLastError = true)]
//static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);
static extern int UpdateResource(IntPtr hUpdate, uint lpType, uint lpName, ushort wLanguage, byte[] lpData, uint cbData);
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr BeginUpdateResource(string pFileName,
[MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
public static void InjectIcon(string execFileName, string iconFileName, uint iconGroupID, uint iconBaseID)
{
const uint RT_ICON = 3;
const uint RT_GROUP_ICON = 14;
// アイコンファイルの読み込み
IconFile iconFile = new IconFile();
iconFile.Load(iconFileName);
// リソースの更新開始
IntPtr hUpdate = BeginUpdateResource(execFileName, false);
Debug.Assert(hUpdate != IntPtr.Zero);
// RT_GROUP_ICON 書き込み
byte[] data = iconFile.CreateIconGroupData(iconBaseID);
UpdateResource(hUpdate, RT_GROUP_ICON, iconGroupID, 0, data, (uint)data.Length);
// RT_ICON書き込み
for (int i = 0; i < iconFile.GetImageCount(); i++)
{
byte[] image = iconFile.GetImageData(i);
UpdateResource(hUpdate, RT_ICON, (uint)(iconBaseID + i), 0, image, (uint)image.Length);
}
// リソースの更新終了
EndUpdateResource(hUpdate, false);
}
}
}
Any help or suggestion on adding the icon to the protected file without corrupting it?
It sounds like the protection application is verifying that the contents of the file haven't been tampered with. Injecting an icon is definitely a form of tampering, and unless the protection software is updated to ignore it, it will always fail. Alternatively if you own the protection software you could update it to not strip the icons.
I just experienced the same issue with a 7zip Self-Extractor exe.
Updating the icon of the 7zS.sfx (instead of the exe) before creating the Self-Extractor exe does the trick and the exe is not corrupted.
Your application's icon can be added to this executable with a tool like Resource Hacker.
and visit http://georezo.net/jparis/MI_Enviro/Icons/adding_w_RH.htm

Set DllImport attribute dynamically

I am making use of an external unmanaged dll using PInvoke and the DllImport attribute. eg.
[DllImport("mcs_apiD.dll", CharSet = CharSet.Auto)]
private static extern byte start_api(byte pid, byte stat, byte dbg, byte ka);
I am wondering if it is possible to alter the dll file details (mcs_apiD.dll in this example) dynmically in some manner, if for instance I wanted to build against another dll version
Yes this is possible, you'll have to do part of the job that the P/Invoke marshaller does. Loading the DLL and finding the entry point of the exported function. Start by declaring a delegate whose signature matches the exported function:
private delegate byte start_api(byte pid, byte stat, byte dbg, byte ka);
Then use code like this:
using System.ComponentModel;
using System.Runtime.InteropServices;
...
static IntPtr dllHandle;
...
if (dllHandle == IntPtr.Zero) {
dllHandle = LoadLibrary("mcs_apiD.dll");
if (dllHandle == IntPtr.Zero) throw new Win32Exception();
}
IntPtr addr = GetProcAddress(dllHandle, "_start_api#16");
if (addr == IntPtr.Zero) throw new Win32Exception();
var func = (start_api)Marshal.GetDelegateForFunctionPointer(addr, typeof(start_api));
var retval = func(1, 2, 3, 4);
...
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string name);
Lots of ways to get this wrong of course. Do note that you have to use the actual exported name from the DLL, you no longer get the help from the P/Invoke marshaller to help with name decoration. Use dumpbin.exe /exports on the DLL if you are not sure what the export name looks like.
you can't change the name of the dll but you can alter the path of the library being loaded (like by reading it from the registry or a configuration file) and load it manually with LoadLibrary kernel32's function: see my answer there.

Categories