I have an ASP.NET web application that stores a HTTP cookie when a certain action has been performed (e.g. a link has been clicked). Now, I am creating a standalone C# app which needs to watch the cookies folder and recognise when a cookie entry has been created by my web application and read the contents of the cookie.
Could anyone please guide me on how to do this in C# or show sample code?
I can't help thinking that is simply the wrong way to do it... and it reaks of security abuse. Is there no better way you could do this? Perhaps hosting the page in a WebBrowser control and using an ObjectForScripting object (of your devising) so you can talk to the C# app from javascript?
You should be able to PInvoke InternetGetCookie.
[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
protected static extern bool InternetGetCookie(
string url,
string name,
StringBuilder cookieData,
ref int length);
You can then call InternetGetCookie like below assuming you are using the Rest Starter Kit.
StringBuilder cookieBuffer = new StringBuilder(1024);
int size = 1024;
bool bSuccess = InternetGetCookie("domain uri", "cookie_name", cookieBuffer, ref size);
if (!bSuccess)
{
Int32 err = Marshal.GetLastWin32Error();
//log err
}
if (cookieBuffer != null && (cookieBuffer.Length > 0))
{
Microsoft.Http.Headers.Cookie cookie = Microsoft.Http.Headers.Cookie.Parse(cookieBuffer.ToString());
HeaderValues<Microsoft.Http.Headers.Cookie> requestCookies = new HeaderValues<Microsoft.Http.Headers.Cookie>();
requestCookies.Add(cookie);
}
There is another thing you can do that could cause your local application to be invoked by the clicking of a link. You'd need to register an application to a URL protocol as seen here. Here is a tutorial and sample app you can look at.
Doing this has it's own set of security implications. However, it is an easy way to invoke your application from the web page and it allows you to pass data via command line params.
Related
I need to set an automatic configuration script that will set the proxy.
When I do this through the LAN settings, all is ok and Chrome is aware of the change immediately. I tried to replicate this behavior by changing the registry key Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings -> AutoConfigURL but Chrome is aware of the change only several minutes after the change (not sure why).
My next attempt is to use Winapi, but I cannot find how to set this script. I found the read function WinHttpDetectAutoProxyConfigUrl that works well, but I cannot find a write equivalent.
How do I setup the autoproxy script with Winapi?
I have a partial answer (only for the setup of the autoproxy). After the registry modification, InternetInitializeAutoProxyDll must be called.
Here is a sample code:
[DllImport("wininet.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern int InternetInitializeAutoProxyDll(uint dwReserved);
// ...
registryKey = Registry.CurrentUser.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Internet Settings", true);
// Setup the registry value:
registryKey.SetValue("AutoConfigURL", "http://the/config/path");
// Tell Windows to initialize the proxy:
if (InternetInitializeAutoProxyDll(0) == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
However, it does not work when the proxy is unset:
registryKey.DeleteValue(AutomaticProxyRegistryName);
// Does nothing:
if (InternetInitializeAutoProxyDll(0) == 0)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
Instead of fiddling directly with the registry I recommend to do everything through the WinINet API. See Programmatically Set Browser Proxy Settings in C# for info on how to do this using C#. Code mentioned in that question can also be found here.
EDIT
The example mentioned fiddles with the registry, too. I have uploaded parts of a program that show how to do everything using WinINet calls. Unfortunately the program is written in Delphi, so you might have to translate it to C#. What is important is that one always resets the proxy settings before setting new values.
So I'm currently trying to check if a user is using a screen reader on our site. The reason I would like to check if they are is because our site provides a training module in which if they are using a screen reader, I would like to show a button that would allow them to download a printable version of the training.
Here is what I have tried so far:
internal class UnsafeNativeMethods
{
public const uint SPI_GETSCREENREADER = 0x0046;
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uiAction, uint uiParam, ref bool pvParam, uint fWinIni);
}
public static class ScreenReader
{
public static bool IsRunning
{
get
{
bool returnValue = false;
if (!UnsafeNativeMethods.SystemParametersInfo(UnsafeNativeMethods.SPI_GETSCREENREADER, 0, ref returnValue, 0))
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "error calling SystemParametersInfo");
}
return returnValue;
}
}
}
I snagged this code from the following StackOverflow thread: C# : How to detect if screen reader is running?
The method I'm using apparently works for some as you can see on this thread, but I'm currently always getting "false" when calling ScreenReader.IsRunning. I'm storing the ScreenReader.IsRunning value in a ViewBag and then in my view I'm using razor syntax to show a button if that value is true. Not really sure why its always false. I have tested this using JAWS as well as Narrator that comes on everyone's computer if you are using Windows 10 I think. Any help would be much appreciated. Thank you all!
It's not possible to detect whether a user is running a screenreader. If it were possible, it would open a door for unscrupulous types to home in on people with disabilities, or for a totally different "accessible" browser experience to be delivered, rather than building interfaces that are inclusive by design.
You could create a button that's placed off-screen but still in the tab order, and make it visible when it receives focus. Then blind users could find it, and sighted keyboard users wouldn't think something strange had happened when the button received focus.
I think you can only check if user has a chrome extensions or something like that working on client side with javascript.
Idea:
You can create an exe or a bath file for check users system and send information about this to your server. If user download this file and there is no screen reader then load the page. Otherwise give error about the screen reader. And when response come from user computer maybe you can use SignalR for show content to user. You can make this file a must works in users system and start downloading this file when user load the page. Its not a good way but maybe you can check this with this way.
The HttpRequest.Browser property returns a HttpBrowserCapabilities object that enlists the capabilities of the device that has made the request. Bear in mind that ASP.NET uses the User-Agent string sent as part of the HTTP request to identify a client. Then to populate the HttpBrowserCapabilities properties, ASP.NET processes the user-agent string using a set of pre-installed browser files, which are contained in the following location: %SystemRoot%\Microsoft.NET\Framework\v4.0.30319\CONFIG\Browsers
HttpBrowserCapabilities Class
There are also third-parties which are far more detailed and updated with detecting device info, i.e. 51Degrees
How I can clear cookies for web browser control winforms C# , is there any way to clear cookies problematically in winforms web browser control
You can disable cache (including cookies) before navigating to the site. To do so, you can use InternetSetOption API function and set the value of INTERNET_OPTION_SUPPRESS_BEHAVIOR(81) option to INTERNET_SUPPRESS_COOKIE_PERSIST(3) value.
Example
The following example, works like starting a new session. While I've logged in to the outlook.com on my machine, but when I open this application and browse outlook.com after disabling cookies and cache, it works like starting a new session and I need to login to outlook.com:
//using System.Runtime.InteropServices;
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool InternetSetOption(IntPtr hInternet, int dwOption,
IntPtr lpBuffer, int dwBufferLength);
private void Form1_Load(object sender, EventArgs e)
{
var ptr = Marshal.AllocHGlobal(4);
Marshal.WriteInt32(ptr, 3);
InternetSetOption(IntPtr.Zero, 81, ptr, 4);
Marshal.Release(ptr);
webBrowser1.Navigate("https://outlook.com");
}
To find more information about these flags, take a look at Windows Internet Option Flags.
Note: You can find a VB.NET version of this answer, here in my other post.
I try to get the full-name of the current log-in user (Fullname, not username).
The following code C#, C++ works fine but on XP computers not connected to the Net, I get empty string as result if I run it ~20 minutes after login (It runs OK whithin the first ~20 minutes after login)
A Win32 API (GetUserNameEx) is used rather that PrincipalContext since it PrincipalContext may takes up to 15 seconds when working offline.
Any Help why am I getting an empty string as result though a user full name is specified???
- C# Code
public static string CurrentUserFullName
{
get
{
const int EXTENDED_NAME_FORMAT_NAME_DISPLAY = 3;
StringBuilder userName = new StringBuilder(256);
uint length = (uint) userName.Capacity;
string ret;
if (GetUserNameEx(EXTENDED_NAME_FORMAT_NAME_DISPLAY, userName, ref length))
{
ret = userName.ToString();
}
else
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception("GetUserNameEx Failed. Error code - " + errorCode);
}
return ret;
}
}
[DllImport("Secur32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool GetUserNameEx(int nameFormat, StringBuilder lpNameBuffer, ref uint lpnSize);
- Code in C++
#include "stdafx.h"
#include <windows.h>
#define SECURITY_WIN32
#include <Security.h>
#pragma comment( lib, "Secur32.lib" )
int _tmain(int argc, _TCHAR* argv[])
{
char szName[100];
ULONG nChars = sizeof( szName );
if ( GetUserNameEx( NameDisplay, szName, &nChars ) )
{
printf( "Name: %s\n", szName);
}
else
{
printf( "Failed to GetUserNameEx\n" );
printf( "%d\n", GetLastError() );
}
return 0;
}
The function GetUserNameEx with NameDisplay can't work in offline mode. This information is only accessible when the computer is online. I recommend you to implement some caching of information like full name or other which is accessible in online mode only. For example, if the computer is online you can retrieve and save information like Full User Name. So you can have in some your config-file of in registry a mapping between users SID and it's full name. If you don't able give full name directly you can get the information from your cash.
Windows has a lot of different notification (like NotifyAddrChange) which you can use (if needed) to monitor change from online to offline mode and back.
Most information which you can get about current user session (also in offline mode) you can get from LsaGetLogonSessionData and WTSQuerySessionInformation API (GetUserNameEx you already know), but you will not find full user name inside.
If you do find a way to get full name of user in offline mode please post the information to me.
Try to use GetUserNameExA (for ASCII) instead of GetUserNameEx macro. Does it help? Print also the output of the program.
I'm curious: for a 'permamently offline' station, where (in the OS) is the user name stored? By browsing control panel Users, it looks like local user accounts have no place to store a 'NameDisplay', there's only a user name.
Where that data is stored for a non-connected node would be a mystery to me. If (in fact) the data is only stored with the domain controller, the only thing I can think of is to cache the information as mentioned earlier.
So use the 1st one, check result and then invoke the 2nd via async delegate. Your app won't get any lag and full name is certainly not it's core feature - I hope :-)
Please try disabling the UAC on your machine. I guess it should work after that.
Steps to disable it.
Go to control panel.
Then to Users.
Select which admin account you wanted to retain.
Delete the account with admin privilege, which you do not wish to have.
If in future you want to create any new account with admin rights, you create an account and make it as an admin account using change account type.
I know that the following should work:
Environment.GetEnvironmentVariable("windir", EnvironmentVariableTarget.Machine)
My problem with this call is that if for some reason someone decided to remove the "windir" Env Var , this won't work.
Is there an even more secure way to get the System drive?
string windir = Environment.SystemDirectory; // C:\windows\system32
string windrive = Path.GetPathRoot(Environment.SystemDirectory); // C:\
Note: This property internally uses the GetSystemDirectory() Win32 API. It doesn't rely on environment variables.
This one returns the path to the system directory (system32).
Environment.GetFolderPath(Environment.SpecialFolder.System)
You may be able to use that, then you don't need to rely on environment variables.
One thing i actually maybe misunderstand is that you want the System Drive, but by using "windir" you'll get the windows folder. So if you need a secure way to get the windows folder, you should use the good old API function GetWindowsDirectory.
Here is the function prepared for C# usage. ;-)
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetWindowsDirectory(StringBuilder lpBuffer, uint uSize);
private string WindowsDirectory()
{
uint size = 0;
size = GetWindowsDirectory(null, size);
StringBuilder sb = new StringBuilder((int)size);
GetWindowsDirectory(sb, size);
return sb.ToString();
}
So if you really need the drive on which windows is running, you could afterwards call
System.IO.Path.GetPathRoot(WindowsDirectory());
You can use the GetWindowsDirectory API to retrieve the windows directory.
Never read environment variables (any script or user can change them !)
The official method (MS internal, used by Explorer) is a Win32 api FAQ for decades (see Google groups, Win32, System api)
Theres an environment variable called SystemDrive
C:\>SET SystemDrive
SystemDrive=C: