Category

Winforms

LoadHtml in CefSharp3

By | Programming, Winforms | No Comments

CefSharp allows you to server an in-app html page via LoadHtml method. Unfortunately all tries serving app related content via this method resulted into blank page. LoadHtml seems to be too inevitable method to load a html content into CefSharp. The only way to make it working as requested is to register a classes derived from ISchemeHandler, ISchemeHandlerFactory (CefSharp sample does it as well).

CustomSchemeHandler class derived from ISchemeHandler

internal class CustomSchemeHandler : ISchemeHandler
    {
        private readonly IDictionary<string, string> resources;
 
        public CustomSchemeHandler()
        {
            resources = new Dictionary<string, string>
            {
                { "/page", Resources.inapppage},
            };
        }
 
        public bool ProcessRequestAsync(IRequest request, ISchemeHandlerResponse response, OnRequestCompletedHandler requestCompletedCallback)
        {
            // The 'host' portion is entirely ignored by this scheme handler.
            var uri = new Uri(request.Url);
            var fileName = uri.AbsolutePath;
 
            string resource;
            if (resources.TryGetValue(fileName, out resource) &&
                !String.IsNullOrEmpty(resource))
            {
                var bytes = Encoding.UTF8.GetBytes(resource);
                response.ResponseStream = new MemoryStream(bytes);
                response.MimeType = GetMimeType(fileName);
                requestCompletedCallback();
 
                return true;
            }
 
            return false;
        }
 
        private string GetMimeType(string fileName)
        {
            if (fileName.EndsWith(".css")) return "text/css";
            if (fileName.EndsWith(".js")) return "text/javascript";
 
            return "text/html";
        }
    }

CustomSchemeHandlerFactory class derived from ISchemeHandlerFactory

    internal class CustomSchemeHandlerFactory : ISchemeHandlerFactory
    {
        public const string SchemeName = "custom";
 
        public ISchemeHandler Create()
        {
            return new CustomSchemeHandler();
        }
    }

Initialization of CustomSchemeHandlerFactory

var settings = new CefSettings();
settings.RegisterScheme(new CefCustomScheme
{
    SchemeName = CustomSchemeHandlerFactory.SchemeName,
    SchemeHandlerFactory = new CustomSchemeHandlerFactory()
});
Cef.Initialize(settings);

To access the in-app html page chnage browser.Address = „custom://test/Page“.

Handle IE Protected Mode in managed code (c#)

By | Programming, Winforms | No Comments

Protected mode helps protect users from attack by running the Internet Explorer process with greatly restricted privileges. File operation are restricted and virtualized and developers must modify theirs application to handle this  behaviour. Your application should detect the protected mode and use special methods from IE’s API ported in managed code.

Here are snipplets in C# how to achieve it.

You must specify C# signatures for the protected mode methods, in our case for saving files.

[DllImport("ieframe.dll")]
public static extern int IECancelSaveFile(IntPtr hState);
 
[DllImport("ieframe.dll")]
public static extern int IEIsProtectedModeProcess(ref bool pbResult);
 
[DllImport("ieframe.dll")]
public static extern int IELaunchURL(IntPtr pszUrl, ref PROCESS_INFORMATION pProcInfo, ref IELAUNCHURLINFO lpInfo);
 
[DllImport("ieframe.dll")]
public static extern int IESaveFile(IntPtr hState, IntPtr lpwstrSourceFile);
 
[DllImport("ieframe.dll")]
public static extern int IEShowSaveFileDialog(
IntPtr hwnd,
IntPtr lpwstrInitialFileName,
IntPtr lpwstrInitialDir,
IntPtr lpwstrFilter,
IntPtr lpwstrDefExt,
uint dwFilterIndex,
uint dwFlags,
ref IntPtr lppwstrDestinationFilePath,
ref IntPtr phState);
 
[DllImport("shell32.dll")]
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);

Protected mode detection and setting LowAppFolder/Temp path:

switch (IEIsProtectedModeProcess(ref isInProtecteMode))
{
case HResults.S_OK:
isInProtecteMode = true;
IntPtr protectedFolderPath;
Guid LowAppFolderGuid = new Guid("{A520A1A4-1780-4FF6-BD18-167343C5AF16}");
if (SHGetKnownFolderPath(LowAppFolderGuid, 0, IntPtr.Zero, out protectedFolderPath) == HResults.S_OK)
{
tempPath = Marshal.PtrToStringUni(protectedFolderPath);
}
Marshal.FreeCoTaskMem(protectedFolderPath);
break;
 
case HResults.E_NOTIMPL:
isInProtecteMode = false;
tempPath = Path.GetTempPath();
break;
}

Save file dialog:

private void SaveFile(string sourcefile, String fileDialogMask, string defaultExtension)
{
IntPtr hState = IntPtr.Zero;
if (isInProtecteMode)
{
Guid LowAppFolderGuid = new Guid("{A520A1A4-1780-4FF6-BD18-167343C5AF16}");
Guid DocumentsLibraryGuid = new Guid("{7B0DB17D-9CD2-4A93-9733-46CC89022E7C}");
IntPtr protectedFolderPath;
IntPtr documentsLibraryPathIntPtr;
IntPtr defaultExtensionIntPtr = Marshal.StringToHGlobalUni(defaultExtension);
IntPtr targetDirIntPtr = IntPtr.Zero;
IntPtr sourceFilenameIntPtr = Marshal.StringToHGlobalUni(Path.GetFileName(sourcefile));
IntPtr fileDialogMaskIntPtr = Marshal.StringToHGlobalUni(fileDialogMask + "|");
IntPtr protectedfilenamePathIntPtr = IntPtr.Zero;
if (SHGetKnownFolderPath(LowAppFolderGuid, 0, IntPtr.Zero, out protectedFolderPath) == HResults.S_OK)
{
protectedfilenamePathIntPtr = Marshal.StringToHGlobalUni(sourcefile);
if (SHGetKnownFolderPath(DocumentsLibraryGuid, 0, IntPtr.Zero, out documentsLibraryPathIntPtr) == HResults.S_OK)
{
int dialogResult = IEShowSaveFileDialog(
this.Handle,
sourceFilenameIntPtr,
documentsLibraryPathIntPtr,
fileDialogMaskIntPtr,
defaultExtensionIntPtr,
1,
0,
ref targetDirIntPtr,
ref hState);
if (dialogResult == HResults.S_OK)
{
int saveResult = IESaveFile(hState, protectedfilenamePathIntPtr);
if (saveResult == HResults.S_OK)
{
// successfully saved
}
}
else
{
int saveResult = IECancelSaveFile(hState);
}
}
Marshal.FreeCoTaskMem(protectedFolderPath);
Marshal.FreeCoTaskMem(documentsLibraryPathIntPtr);
Marshal.FreeCoTaskMem(defaultExtensionIntPtr);
Marshal.FreeCoTaskMem(sourceFilenameIntPtr);
Marshal.FreeCoTaskMem(fileDialogMaskIntPtr);
Marshal.FreeCoTaskMem(targetDirIntPtr);
Marshal.FreeCoTaskMem(protectedfilenamePathIntPtr);
}
}
else {
SaveFileDialog saveasdialog = new SaveFileDialog();
saveasdialog.Filter = fileDialogMask;
saveasdialog.FilterIndex = 1;
saveasdialog.DefaultExt = defaultExtension;
saveasdialog.InitialDirectory = Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
DialogResult result = saveasdialog.ShowDialog();
 
if (result == DialogResult.OK)
{
File.Copy(sourcefile,saveasdialog.FileName,true);
}
}
File.Delete(sourcefile);
}

HResult c# class:

internal sealed class HResults {
internal const int S_OK                   = 0;
internal const int E_NOTIMPL              = unchecked((int)0x80004001);
internal const int E_POINTER              = unchecked((int)0x80004003);
internal const int E_FAIL                 = unchecked((int)0x80004005);
internal const int E_FILENOTFOUND         = unchecked((int)0x80070002);
internal const int E_PATHNOTFOUND         = unchecked((int)0x80070003);
internal const int E_ACCESSDENIED         = unchecked((int)0x80070005);
internal const int E_INVALID_DATA         = unchecked((int)0x8007000D);
internal const int E_OUTOFMEMORY          = unchecked((int)0x8007000E);
internal const int E_INVALIDARG           = unchecked((int)0x80070057);
internal const int E_INSUFFICIENT_BUFFER  = unchecked((int)0x8007007A);
internal const int WSAECONNABORTED        = unchecked((int)0x80072745);
internal const int WSAECONNRESET          = unchecked((int)0x80072746);
internal const int ERROR_TOO_MANY_CMDS    = unchecked((int)0x80070038);
internal const int ERROR_NOT_SUPPORTED    = unchecked((int)0x80070032);
private HResults() {}
}

c#: System.IO.FileNotFoundException in winforms

By | SharePoint, Winforms | No Comments

Have you faced to the FileNotFoundException error message in your WinForms SharePoint application despite the fact that you have all necessary permissions?

System.IO.FileNotFoundException: The Web application at http:// could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.

Maybe you read this article
but the workaround actually does not work? What your winform app deals with app
settings? Nothing, the problem is somewhere else.

Solution: Try to check out winform‘s target platform and server’s platform. They
should be the same. The error occurs in the SPSite constructor, try to  switch to the same
target platform and to avoid the problem.