T
Tony Pitman
I am trying to execute an external application from within a C# .NET Compact
Framework Assembly. I followed a suggested way of creating some helper
classes to marshal the string pointers for me. What I get is that the call
to ShellExecuteEx is failing and the Marshal.GetLastWin32Error returns
0x8000005 which is defined as Access Denied as far as I know.
At first I thought maybe it was that repllog.exe is not allowed to be called
in this way, so I tried to simply invoke calc.exe and that gives the same
results.
Here is the whole code: You might want to copy it out and into a dev
environ for better viewing. Basically the Memory class allocates memory for
the strings in the structure using local alloc and such. The StringPtr class
uses the Memory class to actually contain the strings and then the
SHELLEXECUTEINFO stuct uses the StringPtr to handle the strings.
With this in a project during debugging I have verified that the memory of
the structure does indeed look like it should and the strings are all
unicode style CE type strings and the memory addresses look right. So, why
do I get the access denied error from ShellExecuteEx?
namespace DotNetSyncMgr
{
public class Memory
{
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalAlloc(int uFlags, int uBytes);
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalReAlloc(IntPtr hMem, int uBytes, int
fuFlags);
private const int LMEM_FIXED = 0;
private const int LMEM_MOVEABLE = 2;
private const int LMEM_ZEROINIT = 0x40;
private const int LPTR = (LMEM_FIXED | LMEM_ZEROINIT);
public static IntPtr AllocHLocal(int cb)
{
return LocalAlloc(LPTR, cb);
}
public static void FreeHLocal(IntPtr hLocal)
{
if (!hLocal.Equals(IntPtr.Zero))
{
if (!IntPtr.Zero.Equals(LocalFree(hLocal)))
{
throw (new Exception(Marshal.GetLastWin32Error().ToString()));
}
hLocal = IntPtr.Zero;
}
}
public static IntPtr ReAllocHLocal(IntPtr pv, int cb)
{
IntPtr newMem = LocalReAlloc(pv, cb, LMEM_MOVEABLE);
if (newMem.Equals(IntPtr.Zero))
{
throw (new OutOfMemoryException());
}
return newMem;
}
public static IntPtr StringToHLocalUni(string s)
{
if (s == "" || s == null)
return IntPtr.Zero;
int nc = s.Length;
int len = 2 * (1 + nc);
IntPtr hLocal = AllocHLocal(len);
if (hLocal.Equals(IntPtr.Zero))
throw (new OutOfMemoryException());
else
Marshal.Copy(s.ToCharArray(), 0, hLocal, s.Length);
return hLocal;
}
}
public struct StringPtr
{
private IntPtr szString;
public StringPtr(string s)
{
this.szString = Memory.StringToHLocalUni(s);
}
public override string ToString()
{
return Marshal.PtrToStringUni(this.szString);
}
public void Free()
{
Memory.FreeHLocal(this.szString);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SHELLEXECUTEINFO: IDisposable
{
public int cbSize;
public int fMask;
public int hwnd;
public StringPtr lpVerb;
public StringPtr lpFile;
public StringPtr lpParameters;
public StringPtr lpDirectory;
public int nShow;
public int hInstApp;
public int lpIDList;
public StringPtr lpClass;
public int hkeyClass;
public int dwHotKey;
public int hIcon;
public int hProcess;
public SHELLEXECUTEINFO(string lpVerb, string lpFile, string lpParameters,
string lpDirectory, string lpClass)
{
this.cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO));
this.fMask = 0;
this.hwnd = 0;
this.lpVerb = new StringPtr(lpVerb);
this.lpFile = new StringPtr(lpFile);
this.lpParameters = new StringPtr(lpParameters);
this.lpDirectory = new StringPtr(lpDirectory);
this.nShow = 0;
this.hInstApp = 0;
this.lpIDList = 0;
this.lpClass = new StringPtr(lpClass);
this.hkeyClass = 0;
this.dwHotKey = 0;
this.hIcon = 0;
this.hProcess = 0;
}
public void Dispose()
{
this.lpVerb.Free();
this.lpFile.Free();
this.lpParameters.Free();
this.lpDirectory.Free();
this.lpClass.Free();
}
}
/// <summary>
/// Summary description for SyncMgr.
/// </summary>
public class SyncMgr
{
[DllImport("shell32.dll", SetLastError = true)]
public static extern int ShellExecuteEx(SHELLEXECUTEINFO shInfo);
public SyncMgr()
{
}
public int Connect(string entryName)
{
SHELLEXECUTEINFO shInfo = new SHELLEXECUTEINFO(null, "calc.exe", null,
@"\Windows", null);
try
{
ShellExecuteEx(shInfo);
}
catch (Exception e)
{
MessageBox.Show(Marshal.GetLastWin32Error().ToString());
}
return 0;
}
}
}
Framework Assembly. I followed a suggested way of creating some helper
classes to marshal the string pointers for me. What I get is that the call
to ShellExecuteEx is failing and the Marshal.GetLastWin32Error returns
0x8000005 which is defined as Access Denied as far as I know.
At first I thought maybe it was that repllog.exe is not allowed to be called
in this way, so I tried to simply invoke calc.exe and that gives the same
results.
Here is the whole code: You might want to copy it out and into a dev
environ for better viewing. Basically the Memory class allocates memory for
the strings in the structure using local alloc and such. The StringPtr class
uses the Memory class to actually contain the strings and then the
SHELLEXECUTEINFO stuct uses the StringPtr to handle the strings.
With this in a project during debugging I have verified that the memory of
the structure does indeed look like it should and the strings are all
unicode style CE type strings and the memory addresses look right. So, why
do I get the access denied error from ShellExecuteEx?
namespace DotNetSyncMgr
{
public class Memory
{
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalAlloc(int uFlags, int uBytes);
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalFree(IntPtr hMem);
[DllImport("coredll.dll", SetLastError = true)]
private static extern IntPtr LocalReAlloc(IntPtr hMem, int uBytes, int
fuFlags);
private const int LMEM_FIXED = 0;
private const int LMEM_MOVEABLE = 2;
private const int LMEM_ZEROINIT = 0x40;
private const int LPTR = (LMEM_FIXED | LMEM_ZEROINIT);
public static IntPtr AllocHLocal(int cb)
{
return LocalAlloc(LPTR, cb);
}
public static void FreeHLocal(IntPtr hLocal)
{
if (!hLocal.Equals(IntPtr.Zero))
{
if (!IntPtr.Zero.Equals(LocalFree(hLocal)))
{
throw (new Exception(Marshal.GetLastWin32Error().ToString()));
}
hLocal = IntPtr.Zero;
}
}
public static IntPtr ReAllocHLocal(IntPtr pv, int cb)
{
IntPtr newMem = LocalReAlloc(pv, cb, LMEM_MOVEABLE);
if (newMem.Equals(IntPtr.Zero))
{
throw (new OutOfMemoryException());
}
return newMem;
}
public static IntPtr StringToHLocalUni(string s)
{
if (s == "" || s == null)
return IntPtr.Zero;
int nc = s.Length;
int len = 2 * (1 + nc);
IntPtr hLocal = AllocHLocal(len);
if (hLocal.Equals(IntPtr.Zero))
throw (new OutOfMemoryException());
else
Marshal.Copy(s.ToCharArray(), 0, hLocal, s.Length);
return hLocal;
}
}
public struct StringPtr
{
private IntPtr szString;
public StringPtr(string s)
{
this.szString = Memory.StringToHLocalUni(s);
}
public override string ToString()
{
return Marshal.PtrToStringUni(this.szString);
}
public void Free()
{
Memory.FreeHLocal(this.szString);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SHELLEXECUTEINFO: IDisposable
{
public int cbSize;
public int fMask;
public int hwnd;
public StringPtr lpVerb;
public StringPtr lpFile;
public StringPtr lpParameters;
public StringPtr lpDirectory;
public int nShow;
public int hInstApp;
public int lpIDList;
public StringPtr lpClass;
public int hkeyClass;
public int dwHotKey;
public int hIcon;
public int hProcess;
public SHELLEXECUTEINFO(string lpVerb, string lpFile, string lpParameters,
string lpDirectory, string lpClass)
{
this.cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO));
this.fMask = 0;
this.hwnd = 0;
this.lpVerb = new StringPtr(lpVerb);
this.lpFile = new StringPtr(lpFile);
this.lpParameters = new StringPtr(lpParameters);
this.lpDirectory = new StringPtr(lpDirectory);
this.nShow = 0;
this.hInstApp = 0;
this.lpIDList = 0;
this.lpClass = new StringPtr(lpClass);
this.hkeyClass = 0;
this.dwHotKey = 0;
this.hIcon = 0;
this.hProcess = 0;
}
public void Dispose()
{
this.lpVerb.Free();
this.lpFile.Free();
this.lpParameters.Free();
this.lpDirectory.Free();
this.lpClass.Free();
}
}
/// <summary>
/// Summary description for SyncMgr.
/// </summary>
public class SyncMgr
{
[DllImport("shell32.dll", SetLastError = true)]
public static extern int ShellExecuteEx(SHELLEXECUTEINFO shInfo);
public SyncMgr()
{
}
public int Connect(string entryName)
{
SHELLEXECUTEINFO shInfo = new SHELLEXECUTEINFO(null, "calc.exe", null,
@"\Windows", null);
try
{
ShellExecuteEx(shInfo);
}
catch (Exception e)
{
MessageBox.Show(Marshal.GetLastWin32Error().ToString());
}
return 0;
}
}
}