Dynamic DLL loading in IIS7 fails - c#

We have two web services Running on separate application pools in IIS7. The web services are identical, what differs is that one connects to the test Database and the other to the live database.
The Web services require a DLL which was written in Delphi to churn out some of the business logic required by the system, which we are loading using Dynamic DLL Loading like so:
public static class DynamicLinking
{
private static int libHandle;
private static string dllName;
public static void init(String pDllName)
{
dllName = pDllName;
libHandle = LoadLibrary(pDllName);
}
public static void fini()
{
FreeLibrary(libHandle);
}
[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);
[DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
static extern bool FreeLibrary(int hModule);
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
delegate bool QryFunction(string domainString, string qryString,
int outputStringBufferSize, ref string outputStringBuffer);
public static void ExecuteDLLFunction(string pfunctionName, int bufferSize,
string pDomain, string inputXMLString,
out string outputString)
{
if (libHandle == 0)
throw new Exception(string.Format("Could not load library \"{0}\"", dllName));
var delphiFunctionAddress = GetProcAddress(libHandle, pfunctionName);
if (delphiFunctionAddress == IntPtr.Zero)
throw new Exception(string.Format("Can't find function \"{0}\" in library \"{1}\"", pfunctionName, dllName));
var queryFunction = (QryFunction)Marshal.GetDelegateForFunctionPointer(delphiFunctionAddress, typeof(QryFunction));
var outputStringBuffer = new String('\x00', bufferSize);
var errorMsgBuffer = new String('\x00', bufferSize);
if (!queryFunction(pDomain, inputXMLString,
bufferSize, ref outputStringBuffer))
throw new Exception(errorMsgBuffer);
outputString = outputStringBuffer;
}
}
Now the problem lies here: when we start the web the websites, which ever site gets started last will fail to load the dll, while the first one to load will run fine.
//edit---------------------------------
What's strange is that when the same DLL is copied in each website this issue arises however, if we link both sites to the same DLL, everything works fine
Any insight on this?

You should out each site in a separate App Pool, so that IIS will run each one in a its own process.

Related

WindowsAccessBridge for Java Automation using C#

I try to automate an java application using WindowsAccessBridge.dll.
I can get the window handle but calling the function isJavaWindow(System.IntPtr hWnd) always return false
Please find my code below:
static void Main()
{
System.Int32 vmID = 0;
System.Int64 _acParent = 0;
string WndName = "GLOBUS EDU";
string ClassName = "SunAwtFrame";
Windows_run();
System.IntPtr hWnd = System.IntPtr.Zero;
hWnd = (System.IntPtr)FindWindow(ClassName, WndName);
bool Found = isJavaWindow(hWnd);
if (!Found) { throw new System.Exception("ERROR: Unable to find window by classname " + ClassName + " and " + WndName + "!"); }
System.Console.WriteLine("Application is finished. Press ENTER to exit...");
System.Console.ReadKey();
}
Interop:
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Bool)]
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
private extern static bool getAccessibleContextFromHWNDFct(System.IntPtr hwnd, out System.Int32 vmID, out System.Int32 _acParent);
private static bool getAccesibleContextFromHWND(System.IntPtr hWnd, out System.Int32 vmID, out System.Int64 acParent)
{
System.Int32 ac = -1;
bool retVal = false;
getAccessibleContextFromHWNDFct(hWnd, out vmID, out ac);
acParent = ac;
return retVal;
}
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl)]
private extern static bool getAccessibleContextInfo(int vmID, System.IntPtr ac, out AccessibleContextInfo textInfo);
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private extern static void Windows_run();
[System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
private static extern System.IntPtr FindWindow(string lpClassName, string lpWindowName);
[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
private static extern System.IntPtr FindWindowByCaptionFct(System.IntPtr ZeroOnly, string lpWindowName);
private static System.IntPtr FindWindowByCaption(string WindowTitle) { return FindWindowByCaptionFct(System.IntPtr.Zero, WindowTitle); }
[System.Runtime.InteropServices.DllImport("WindowsAccessBridge-64.dll", CallingConvention = System.Runtime.InteropServices.CallingConvention.Cdecl, ThrowOnUnmappableChar = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
private extern static System.Boolean isJavaWindow(System.IntPtr hwnd);
The function FindWindowis working perfect and I'm getting the window handle also Spy++ shows me. The classname is SunAwtFrameas Spy++ says.
My Java applications runs in 64 bit but I tried all the Libraries (-32, -64) and also switched in the VS Configuration Manager from x86 to x64 and back.
The AccessBridge itself is working well - Java-Monkey-64.exe can spy my running java application.
Does anybody has an idea, why this is not working?
Regards,
Jan
I have been fighting with your problem in few days.
i created a program that enumerate window that is java application(of course write on console application), and catch same problem like yours.
then, i rewrite it on WPF application,enumerate all window, then recognize that: besides the normal window, i see a strange window named: "java access bridge", and the problem is clearly:
the Windows_run function need to have an active windows message pump.
another way, you must putting it on the constructor of a WPF application or something same that.
if (result != FALSE) {
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
shutdownAccessBridge();
}
code in Java Monkey application.
After create a hidden window, it performs a PostMessage with a registered message. The JVM side of the access bridge responds to this message, and posts back another message to the window that was created. As such, they communicate by that way.
and more, you only can call JAB functions after the message pump can process messages.
that is reason why the java monkey need to use call back for it's business.
Pass null for class name as in the below code:
IntPtr hWnd = FindWindow(null, "GLOBUS EDU"); //cast to IntPtr is redundant
bool Found = isJavaWindow(hWnd);
Reference is here on Pinvoke documentation, and it works for me!

Evaluate if drive is in use

I'd like to evaluate wether a drive is in use (if I'm not mistaken this means that some read/write stuff is happening with the drive) using C#. I wouldn't mind for a solution using bash scripts or similiar either, as I could use them in a C# application. I already found a question regarding bash scripts here, but couldn't solve my problem with the answers given.
I considered to use the DriveInfo class already, however it didn't seem to have anything useful for me. I wondered wether I could use the IsReady property from DriveInfo, because I guessed that it wouldn't be ready while it is read/written, but this attempt seems rather botchy to me.
However I still tried it:
private static bool IsDriveInUse ()
{
var drive = DriveInfo.GetDrives ().FirstOrDefault(info => info.Name.StartsWith(DRIVE_LETTER.ToString()));
return drive != null && !drive.IsReady;
}
But it didn't work (it returned false while I played music from my drive).
An optimal solution for me would be a function that tells me wether the drive was in use in a specific span of time (let's stick to the name IsDriveInUse). That means that if the time was for example 60 seconds, IsDriveInUse should return true if 5 seconds before the function call content from the drive was read and false if there was no read/write action in the passed 60 seconds.
EDIT To specify what exactly I mean by in use, I'll try to explain what I'm trying to do. I am writing a tool, which automatically spins down my hard drive, when it's been idle or when I press a keyboard shortcut. I managed to spin it down programmatically (even though either the windows integrated tool nor other tools I found were able to do that, but that's another problem). However, it now spins down the hard drive every minute, regardless of wether it's currently in use or not. That means, if I play music from my hard drive, it's still spinned down, just to spin up directly after it, which doesn't decrease noise development.
I hope this clarified the matter.
EDIT I now tried using the FSCTL_LOCK_VOLUME control code (I couldn't find a value for IOCTL_DISK_PERFORMANCE), but it still returned false for IsDriveInUse() while I was playing music. Furthermore it caused windows to directly spin the drive up again as I spinned it down (probably because the releasing made Windows think that something was using the drive). This is what I tried:
public class DriveManager
{
public const int FSCTL_LOCK_VOLUME = 0x00090018;
public const int FSCTL_UNLOCK_VOLUME = 0x0009001c;
[DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CreateFile (
string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes,
uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[return: MarshalAs (UnmanagedType.Bool)]
[DllImport ("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeviceIoControl (
[In] SafeFileHandle hDevice,
[In] int dwIoControlCode, [In] IntPtr lpInBuffer,
[In] int nInBufferSize, [Out] IntPtr lpOutBuffer,
[In] int nOutBufferSize, out int lpBytesReturned,
[In] IntPtr lpOverlapped);
public static SafeFileHandle CreateFileR (string device)
{
string str = device.EndsWith (#"\") ? device.Substring (0, device.Length - 1) : device;
return new SafeFileHandle (
CreateFile (#"\\.\" + str, WinntConst.GENERIC_READ, WinntConst.FILE_SHARE_READ, IntPtr.Zero,
WinntConst.OPEN_EXISTING, WinntConst.FILE_ATTRIBUTE_NORMAL, IntPtr.Zero), true);
}
internal class WinntConst
{
// Fields
internal static uint FILE_ATTRIBUTE_NORMAL = 0x80;
internal static uint FILE_SHARE_READ = 1;
internal static uint GENERIC_READ = 0x80000000;
internal static uint OPEN_EXISTING = 3;
}
public static bool IsDriveInUse (string deviceName)
{
var handle = CreateFileR (deviceName);
var buffer = Marshal.AllocHGlobal (sizeof (int));
try
{
return
DeviceIoControl (handle,
FSCTL_LOCK_VOLUME,
IntPtr.Zero,
0,
buffer,
sizeof(int),
out var bytesReturned,
IntPtr.Zero
);
}
finally
{
var sessionId = Marshal.ReadInt32 (buffer);
Marshal.FreeHGlobal (buffer);
handle.Close ();
}
}
And the implementation:
private static bool IsDriveInUse () => DriveManager.IsDriveInUse ($#"{DRIVE_LETTER}:\");
Maybe it helps to see the part in which I'm spinning the disc down as well (I used Smartmontools for this):
internal static class Program
{
private const string PROGRAM_PATH = #"External\smartctl.exe";
private const string ARGUMENTS_SHUTDOWN = #"-s standby,now {0}:";
private const char DRIVE_LETTER = 'd';
public static void Main (string [] args)
{
InitializeHotKey ();
Console.WriteLine ("Hotkey registered!");
while (true)
{
Thread.Sleep (60000);
if (!IsDriveInUse ())
ShutDownDrive (true);
}
}
private static bool IsDriveInUse () => DriveManager.IsDriveInUse ($#"{DRIVE_LETTER}:\");
private static void InitializeHotKey ()
{
HotKeyManager.RegisterHotKey (Keys.D, KeyModifiers.Alt | KeyModifiers.Control);
HotKeyManager.HotKeyPressed += HotKeyPressed;
}
private static void HotKeyPressed (object sender, HotKeyEventArgs hotKeyEventArgs) => ShutDownDrive (true);
private static void ShutDownDrive (bool withDialog = false)
{
Process process;
(process = new Process
{
StartInfo = new ProcessStartInfo
{
WindowStyle = ProcessWindowStyle.Hidden,
FileName = PROGRAM_PATH,
Arguments = string.Format (ARGUMENTS_SHUTDOWN, DRIVE_LETTER)
}
}).Start ();
process.WaitForExit ();
process.Close ();
if (withDialog)
Console.WriteLine ("Drive shut down!");
}
}
Perhaps you could use the Windows Performance Counter relevant to your drive ?
"Disk Read/sec" seems quite relevant for what youhave in mind.
In .Net, the counters are available via System.Diagnostics.PerformanceCounter
see there :
https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter(v=vs.110).aspx

Using kernel32 CreateThread/TerminateThread inside Azure Worker Role

I have this code that I need to use, but what holds me back is that here it says that TerminateThread Applies to: desktop apps only.
I wonder if I can use this code inside azure Worker role, specifically inside waiishost.exe process that I use to run the Worker thread in?
[DllImport("Library.dll")]
public static extern void InfiniteLoop();
[DllImport("kernel32")]
private static extern int CreateThread(
IntPtr lpThreadAttributes,
UInt32 dwStackSize,
IntPtr lpStartAddress,
IntPtr param,
UInt32 dwCreationFlags,
UInt32 lpThreadId
);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern int TerminateThread(int hThread);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetLastError();
private delegate int InvokeInfiniteLoop(IntPtr args);
static void Main(string[] args)
{
InvokeInfiniteLoop invokeInfiniteLoop = (args1) =>
{
InfiniteLoop();
return 0;
};
IntPtr infiniteLoopPtr = Marshal.GetFunctionPointerForDelegate(invokeInfiniteLoop);
int handle = CreateThread(IntPtr.Zero, 0, infiniteLoopPtr, IntPtr.Zero, 0, 0);
Thread.Sleep(TimeSpan.FromSeconds(5));
int terminated = TerminateThread(handle);
Console.WriteLine(terminated);
}
EDIT:
After further research looks like(as I suspected from the beginning) that this workaround is completely wrong. Creating and Terminating the unmanaged code will leak the stack. I will have to create a separate executable that will be terminated by Process.Kill();
The "Applies to: desktop apps only" refers to the difference between Windows 8 Desktop application and Windows 8 Metro applications.

Can't find SDL_LoadBMP() entry point in 'SDL.DLL' with PInvoke

I'm trying to marshal data between SDL and my C# .NET program. The first few calls that I make into SDL.DLL work fine, inasmuch as I get no error and my Windows console app does open an empty application window:
My_SDL_Funcs.SDL_Init(0x0000FFFF); // SDL_INIT_EVERYTHING
IntPtr scrn = My_SDL_Funcs.SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0x00000000); // SDL_SWSURFACE
screen = (SDL_Surface)Marshal.PtrToStructure(scrn, typeof(SDL_Surface));
My_SDL_Funcs.SDL_WM_SetCaption("Hello World", null);
// ...
When I try to call SDL_LoadBMP() however, I get this runtime error:
Unable to find an entry point named 'SDL_LoadBMP' in DLL 'SDL'.
The SDL doc says that SDL_LoadBMP takes a const char* file name and returns a pointer to a SDL_Surface struct.
I first tried declaring the PInvoke as:
[DllImport("SDL", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr SDL_LoadBMP([MarshalAs(UnmanagedType.LPWStr)] string file);
When this didn't work, I tried:
public static extern IntPtr SDL_LoadBMP(IntPtr file);
and used:
IntPtr fn = Marshal.StringToHGlobalAnsi(filename);
IntPtr loadedImage = My_SDL_Funcs.SDL_LoadBMP(fn);
Assuming that that the function actuall does exist in this library (SDL.DLL version 1.2.14), am I using the wrong invocation for a const char*?
I downloaded the DLL version you are using, and could not find an export for SDL_LoadBMP.
There is a SDL_LoadBMP_RW, though, so you could rig up your own helper call like so:
private const string SDL = "SDL.dll";
[DllImport(SDL, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr SDL_LoadBMP_RW(IntPtr src, int freesrc);
[DllImport(SDL, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr SDL_RWFromFile(string file, string mode);
public static IntPtr SDL_LoadBMP(string file)
{
return SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1);
}
UPDATE:
I had a look through the code, and the call you are looking for is defined as a macro, so that is why you can't call it directly. Using the above code basically does the same thing as the macro defintion:
#define SDL_LoadBMP(file) SDL_LoadBMP_RW(SDL_RWFromFile(file, "rb"), 1)

Programmatically install Certificate Revocation List (CRL)

I need to download and install about 50 CRLs once a week and install them on several Windows servers. Downloading is the easy part, is there a way I could script the CRL import process?
Here is my final source (slightly scrubbed for the public) - but should work. I won't change the accepted answer, but I do hope this helps (as does upvoting the question and answers!).
Note: This will import both a CRL or a regular certificate into the LOCAL MACHINE Trusted Root store. Changing the below CERT_SYSTEM_STORE_LOCAL_MACHINE to CERT_SYSTEM_STORE_CURRENT_USER in the call CertOpenStore will change it to work for the Current User store.
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
class Program
{
public struct CRYPTUI_WIZ_IMPORT_SRC_INFO
{
public Int32 dwSize;
public Int32 dwSubjectChoice;
[MarshalAs(UnmanagedType.LPWStr)]public String pwszFileName;
public Int32 dwFlags;
[MarshalAs(UnmanagedType.LPWStr)]public String pwszPassword;
}
[DllImport("CryptUI.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean CryptUIWizImport(
Int32 dwFlags,
IntPtr hwndParent,
IntPtr pwszWizardTitle,
ref CRYPTUI_WIZ_IMPORT_SRC_INFO pImportSrc,
IntPtr hDestCertStore
);
[DllImport("CRYPT32.DLL", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CertOpenStore(
int storeProvider,
int encodingType,
IntPtr hcryptProv,
int flags,
String pvPara
);
public const Int32 CRYPTUI_WIZ_IMPORT_SUBJECT_FILE = 1;
public const Int32 CRYPT_EXPORTABLE = 0x00000001;
public const Int32 CRYPT_USER_PROTECTED = 0x00000002;
public const Int32 CRYPTUI_WIZ_NO_UI = 0x0001;
private static int CERT_STORE_PROV_SYSTEM = 10;
private static int CERT_SYSTEM_STORE_CURRENT_USER = (1 << 16);
private static int CERT_SYSTEM_STORE_LOCAL_MACHINE = (2 << 16);
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.WriteLine("Usage: certimp.exe list.crl");
Environment.ExitCode = 1;
}
else
{
IntPtr hLocalCertStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
IntPtr.Zero,
CERT_SYSTEM_STORE_LOCAL_MACHINE,
"ROOT"
);
CRYPTUI_WIZ_IMPORT_SRC_INFO importSrc = new CRYPTUI_WIZ_IMPORT_SRC_INFO();
importSrc.dwSize = Marshal.SizeOf(importSrc);
importSrc.dwSubjectChoice = CRYPTUI_WIZ_IMPORT_SUBJECT_FILE;
importSrc.pwszFileName = args[0];
importSrc.pwszPassword = null;
importSrc.dwFlags = CRYPT_EXPORTABLE | CRYPT_USER_PROTECTED;
if (!CryptUIWizImport(
CRYPTUI_WIZ_NO_UI,
IntPtr.Zero,
IntPtr.Zero,
ref importSrc,
hLocalCertStore
))
{
Console.WriteLine("CryptUIWizImport error " + Marshal.GetLastWin32Error());
Environment.ExitCode = -1;
}
}
}
}
}
I don't know a way to do it via script.
Can you write C code? If I understand what you want to do, you will use the CryptUiWizImport function, and the CRYPTUI_WIZ_IMPORT_SRC_INFO structure.
Here's a sample of code that installs a Cert; the corresponding CRL import is similar.
Addendum:
This post points out that Win32 APIs (such as CryptUiWizImport) are not directly accessible from PowerShell, and then describes a possible workaround: from within the PowerShell script, dynamically generate and compile C# code that does the P/Invoke stuff, and then run the resulting assembly. This would allow you to do the CryptUiWizImport strictly from a powershell script, although it would be a pretty exotic one.
Hm. Is there any reason not to use the certutil.exe utility? I can import a Certificate Revocation List into the appropriate store by running the following command:
certutil -addstore CA <FileName>.crl
In Powershell there is a Cert: provider which represents the certificate store. Manipulating it is done via the standard cmdlets so you might be able to integrate a revocation list there somewhere. I just don't know enough about how Windows handles certificates to be of any further help here.
We have to use only Win32 Apis to do this. There is no firstclass C# system APIs to do this. Refer https://stackoverflow.com/a/67814697/3671594

Categories