I have a pretty standard MVC3 application. I'm trying to store some data that's application-wide (not user wide) in a the cache (in this case, a Theme object/name). When debugging (on the development server that integrates with Visual Studio), if I call SwitchTheme, I see the new theme right away. On IIS7, whatever theme was cached, stays cached; it doesn't update to the new theme.
Edit: Some code:
public static Theme CurrentTheme { get {
Theme currentTheme = HttpContext.Current.Cache[CURRENT_THEME] as Theme;
if (currentTheme == null)
{
string themeName = DEFAULT_THEME;
try
{
WebsiteSetting ws = WebsiteSetting.First(w => w.Key == WebsiteSetting.CURRENT_THEME);
if (ws != null && !string.IsNullOrEmpty(ws.Value))
{
themeName = ws.Value;
}
}
catch (Exception e)
{
// DB not inited, or we're installing, or something broke.
// Don't panic, just use the default.
}
// Sets HttpContext.Current.Cache[CURRENT_THEME] = new themeName)
Theme.SwitchTo(themeName);
currentTheme = HttpContext.Current.Cache[CURRENT_THEME] as Theme;
}
return currentTheme;
} }
public static void SwitchTo(string name)
{
HttpContext.Current.Cache.Insert(CURRENT_THEME, new Theme(name), null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
// Persist change to the DB.
// But don't do this if we didn't install the application yet.
try
{
WebsiteSetting themeSetting = WebsiteSetting.First(w => w.Key == WebsiteSetting.CURRENT_THEME);
if (themeSetting != null)
{
themeSetting.Value = name;
themeSetting.Save();
}
// No "else"; if it's not there, we're installing, or Health Check will take care of it.
}
catch (Exception e)
{
// DB not inited or install not complete. No worries, mate.
}
}
I'm not sure where the problem is. I am calling the same method and updating the cache; but IIS7 just shows me the old version.
I can disable output caching in IIS, but that's not what I want to do. That seems like a hacky work-around at best.
Without a code sample it's difficult to know what your problem is. In an attempt to provide some assistance, here is how I frequently set the cache in my applications:
public static void SetCache(string key, object value) {
if (value != null) {
HttpRuntime.Cache.Insert(key, value, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
}
}
The HTTP cache is reset only if you do so manually or the app domain (or app pool) resets for whatever reason. Are you sure that's not happening in this case? And generally speaking, any global static variables would also be maintained in memory under the same circumstances.
There are many reasons why an app pool might be reset at any given point, such as a change to a web.config file, etc. I suggest checking that's not happening in your case.
By the way, output caching is a different thing, although it is maintained in memory largely the same way.
Given that this only happens on IIS7 when Output Caching is not disabled, this seems very likely to be an IIS7 bug. Seriously.
Whether it is or not, is irrelevant to the solution. What you need to do is find some manual process of invalidating the cache, such as touching the web.config file.
But beware: doing this will wipe out the cache (as you expect), but also all static variables (as a side-effect). Whether this is another bug or not, I don't know; but in my case, this was sufficient to solve the problem.
Related
I’m having issues with a static member of my app class losing its value and I’m not quite sure I understand why. In my app constructor I check if the user is logged in and if not redirect to a login page where I set the static app class member.
I understand if the app is forced to close to free up resources, these values are not retained so a new app instance would start and go back to login screen. However, what I’m seeing is the static member losing its value during an application session. I can do a check to see if this is null on resume and redirect to login page but I don’t understand why this happens.
My understaning was that the only way you would lose values would be if the app was killed in the background but this problem would suggest it can happen when resuming too.
In a normal C# application static members will typically survive forever, but unfortunately your observations are entirely correct; in Xamarin Forms static members are not guaranteed to persist for the length of the application's life.
In Android's case if the underlying platform indicates a low memory state (or increased demands on memory from multiple running applications) then static members are considered collectable by the GC, which is often triggered when you pause the application (ie. switching to a different app). They will be reduced to their default value, eg. null, zero, etc.
I've wrestled with this curio for years, and the most performant work around is to implement a re-population pattern on those static members, eg.
internal List<MyCustomType> _AListOfStuff
internal List<MyCustomType> AListOfStuff
{
get
{
if (_AListOfStuff == null)
{
PopulateAListOfStuff(); //If this occurs then the static member has been garbage collected: reload it
}
return _AListOfStuff;
}
}
From what you've said, I appreciate that your particular usage of static members probably doesn't fit with this solution, however all I can offer is that you're not crazy; it is a documented quirk, and not considered a bug (don't even bother shaking that tree; I've been down that route with the devs and was told in no uncertain terms that the behaviour is here to stay, and is necessary to ensure overall device stability).
Static member will not lose. If we see the code then we can assist further. Another approach would be, try using singleton pattern, it will create new instance only if it's instance is null. sample below:
public sealed class SingletonSample
{
private static SingletonSample instance = null;
private static readonly object padlock = new object();
public static SingletonSample Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new SingletonSample();
}
return instance;
}
}
}
public string FirstName { get; set; }
}
Does anybody know how I can programmatically check (using C#) whether my program will be able to read / write a particular registry key (specifically: "SOFTWARE\Microsoft\Windows\CurrentVersion\Run")?
I am asking because my program has the option to enable or disable the 'run at startup' behaviour. I want to disable this option if the current user is not allowed to make changes to the registry. Is this key always allowed to be written by the current user, or is there the possibility that it has been locked down? If the latter, how do I check this?
I have seen several conflicting ways of checking registry permissions - but basically I can't find a way to check a specific key before I try to read it. I would rather perform the check before accessing the key than trying to access it and receive an exception.
Any help is much appreciated.
Tom
The RegistryPermission class governs the security permissions around reg keys. To check if you may have write access to a permission you use it in the following manner:
RegistryPermission perm1 = new RegistryPermission(RegistryPermissionAccess.Write, #"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
You would then use the "Demand" method in a try/catch and return on failure (the raising of a security exception). On success you'd carry on and perform your update. Although this isn't quite what you want, a check on permissions before access, it is the accepted way of ensuring you have the permissions you need before you operate on the keys. In a fully structured manner this would equate to:
try
{
RegistryPermission perm1 = new RegistryPermission(RegistryPermissionAccess.Write, #"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
perm1.Demand();
}
catch (System.Security.SecurityException ex)
{
return;
}
//Do your reg updates here
EDIT: Thinking on what I mentioned in the comment, here are extension methods to the RegistryPermission class for permission checks:
using System.Security.Permissions;
using System.Security;
public static class RegistryExtensions
{
public static bool HavePermissionsOnKey(this RegistryPermission reg, RegistryPermissionAccess accessLevel, string key)
{
try
{
RegistryPermission r = new RegistryPermission(accessLevel, key);
r.Demand();
return true;
}
catch (SecurityException)
{
return false;
}
}
public static bool CanWriteKey(this RegistryPermission reg, string key)
{
try
{
RegistryPermission r = new RegistryPermission(RegistryPermissionAccess.Write, key);
r.Demand();
return true;
}
catch (SecurityException)
{
return false;
}
}
public static bool CanReadKey(this RegistryPermission reg, string key)
{
try
{
RegistryPermission r = new RegistryPermission(RegistryPermissionAccess.Read, key);
r.Demand();
return true;
}
catch (SecurityException)
{
return false;
}
}
}
One thing you should know about permissions is that they are volatile. That means you could do your security check on the registry key, attempt to add your value only if the check passes, and then still fail with an insufficient access exception because the permissions changed in between when you made the check and when you acted on the results. This is possible even if they are consecutive statements in your program.
Granted security permissions tend to be relatively stable, but the chance still exists. This means that you must have code to handle the security exception, and if you have to do that anyway there's not really any point in making the check in the first place. Instead, put your time into making your exception handler a little bit better.
That said, "boo" to any app that wants to run something at start-up. YAGNI.
I think you best bet is to just try to add your value to the key, and handle failure gracefully by informing the user they didn't have enough permissions to do that.
If you're writing some sort of administrative tool that is designed to always be run by an administrator, you should indicate that in the manifest. That way your app will elevate at startup (via UAC prompt).
Simplest option is to try and open the key with write access and see if you get it. Remember to close the key afterwards.
bool fWriteAccess;
try {
Registry.LocalMachine.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run", True).Close();
fWriteAccess = True;
} catch (SecurityException) {
fWriteAccess = False;
}
I'm not sure how to it with C#, but with Win32, you would use RegGetKeySecurity(). Maybe there's a C# wrapper? Otherwise, use P/Invoke.
Just try to open the registry key with WRITE permissions.
That said, what others have said is right: There is no way to tell if an operation is going to succeed unless you try it. Maybe someon deleted the Run key. Maybe the registry will exceed allocated memory. Maybe the disk failed.
VS2010 is driving me nuts: whenever I rebuild, the "Error List" warnings from the previous compilation are persisted and any new warnings are simply added to the end of the list. Over time, this list becomes ridiculously long and unwieldy.
I'm using the Chirpy 2.0 tools to run JSHint and JSLint on my JS files, and these tools generate a lot of false positives.
I've been looking for an easy way to clear the contents of this window, but the only manual mechanism that works 100% of the time is to close and re-open the solution. Not very elegant.
I'd like to write a small VS Plug-In or some code that gets called right before a compilation to clear out this list so I can focus only on new warnings for the currently loaded file(s).
I see a .Clear() method for the Output window but not for the Error List. Is this doable?
Once upon a time I was an Add-In/VSIX Package/MEF developer ...
The answer is shortly no, but I have to do it on the long way:
Add-Ins, packages (Managed or not) have access to the VS service level separatedly. Every error belongs to the reporter (If they are manage them as Chirpy do), so you can not handle the errors created by Chirpy 2.0
I take a several look to it's source code and it is persist it's erros gained by the tools in a Singleton collection called TaskList.
The deletion of the collection elements is happening in several point of code in the latest release through the RemoveAll method:
First: after the soulution is closed.
by this:
private static string[] buildCommands = new[] { "Build.BuildSelection", "Build.BuildSolution", "ClassViewContextMenus.ClassViewProject.Build" };
private void CommandEvents_BeforeExecute(string guid, int id, object customIn, object customOut, ref bool cancelDefault) {
EnvDTE.Command objCommand = default(EnvDTE.Command);
string commandName = null;
try {
objCommand = this.App.Commands.Item(guid, id);
} catch (System.ArgumentException) {
}
if (objCommand != null) {
commandName = objCommand.Name;
var settings = new Settings();
if (settings.T4RunAsBuild) {
if (buildCommands.Contains(commandName)) {
if (this.tasks != null) {
this.tasks.RemoveAll();
}
Engines.T4Engine.RunT4Template(this.App, settings.T4RunAsBuildTemplate);
}
}
}
}
As you may see, clear of results depends on many thigs.
First on a setting (which I don't know where to set on GUI or configs, but seems to get its value form a check box).
Second the array of names which are not contains every build commands name.
So I see a solution, but only on the way to modify and rebuild/redepeloy your own version from Chirpy (and make a Pull request):
The code souldn't depend on the commands, and their names. (rebuilds are missing for example)
You could change the method above something like this:
this.eventsOnBuild.OnBuildBegin += ( scope, action ) =>
{
if (action != vsBuildAction.vsBuildActionDeploy)
{
if (this.tasks != null)
{
this.tasks.RemoveAll();
}
if (settings.T4RunAsBuild && action != vsBuildAction.vsBuildActionClean)
{
Engines.T4Engine.RunT4Template(this.App, settings.T4RunAsBuildTemplate);
}
}
};
Or with something equivalent handler method instead of lambda expression.
You shold place it into the subscription OnStartupComplete method of Chirp class.
The unsubscription have to placed into OnDisconnection method in the same class. (As for all other subscribed handlers...)
Update:
When an Add-In disconneced, it isn't means the Studio will be closed immediately. The Add-In could be unloaded. So you should call the RemoveAll from OnDisconneconnection too. (Or Remove and Dispose the TaskList...)
Update2:
You can also make a custom command, and bind it to a hotkey.
Update: I have dropped the cache system in favor of a database solution - pitty.
I have a backend MVC controller where i need data caching. I use MemoryCache.Default to store key/value pairs, nothing big. Nevermind policies and expire times, i'f got that. The thing that mystifys me is why my cache gets cleaned out after I'f accessed a key (retrived the value) the first time. If i don't access the cached item, eventually the item will expire and my remove handler is called - it's all good. But when i retrive the item the first time, my remove handler is called after a short while. The ChacheEntryRemovedReason is set to:
CacheSpecificEviction // A cache entry was evicted for as reason that is defined by a particular cache implementation.
I can't find any explanation to what this means.
The mystifying thing here is that when i inspect the cache object when debugging in the handler (and on succeeding controller calls), the cache enum is empty. If I "set" (add) a new CacheItem to the cache, I can yet again access the key once, and history repeats.
The behavior is like a one-off caching mechanism which i totally don't need.
Any help or comments would be much appreciated!
Some simplified code just for the fun of it:
private static ObjectCache cache = MemoryCache.Default;
internal void insertInCache(string key, int value) {
CacheItemPolicy policy= new CacheItemPolicy() {
AbsoluteExpiration = ObjectCache.InfiniteAbsoluteExpiration,
Priority = CacheItemPriority.NotRemovable,
SlidingExpiration = TimeSpan.FromMinutes(ITEM_EXPIRE_TIME),
RemovedCallback = new CacheEntryRemovedCallback(RemovedHandler)
};
cache.Set(key, value, policy);
}
static void RemovedHandler(CacheEntryRemovedArguments args) {
if(args.RemovedReason == CacheEntryRemovedReason.Expired) {
//do something - or i actually want it to disappear when expired
} else {
cache.Set(args.CacheItem, somepolicy);//reinsert to keep in cache
}
}
//Apparently this triggers some cache mong mode
internal void getSome(string key){
int thisIsWhatIWanted = (int)cache.GetCacheItem(key).Value;
}
This is just example code so please don't nag me about my skillz.
My own best guess is that it may have to do with the cache not being setup properly, MVC witchery or the fact I'm running my application on a debug IIS (visual studido)
I am writing a command-line tool for Windows that uses libcurl to download files from the internet.
Obviously, the downloading doesn't work when the user is behind a proxy server, because the proxy needs to be configured. I want to keep my tool as simple as possible however, and not have to burden the user with having to configure the proxy. My tool doesn't even have a config file, so the user would otherwise have to pass in the proxy settings on every command, or set an environment variable or somesuch -- way too much hassle.
So I thought, everyone's browser will usually already be set up properly, proxy configured and everything. This will be true for even the most basic user because otherwise "their internet wouldn't work".
So I figure that I can find out whether to use a proxy by looking at IE's proxy settings.
How do I go about this? More specifically:
Is there one set of "proxy settings" in Windows, used by all browsers (probably IE's), or would I have to write different routines for IE, Firefox, Opera, etc?
I know that I can probably read the values directly out of the appropriate registry locations if they are configured manually, but does this also work with "automatically detect proxy server?" Do I even have to bother with that option, or is it (almost) never used?
Before people start suggesting alternatives: I'm using C, so I'm limited to the Win32 API, and I really really want to keep using C and libcurl.
The function you're looking for is WinHttpGetIEProxyConfigForCurrentUser(), which is documented at http://msdn.microsoft.com/en-us/library/aa384096(VS.85).aspx. This function is used by Firefox and Opera to get their proxy settings by default, although you can override them per-browser. Don't do that, though. The right thing to do (which is what everybody else does) is to just get the IE settings and assume that they're correct, since they almost always are.
Here's a sample of the relevant logic, which you should adapt for your needs:
if( WinHttpGetIEProxyConfigForCurrentUser( &ieProxyConfig ) )
{
if( ieProxyConfig.fAutoDetect )
{
fAutoProxy = TRUE;
}
if( ieProxyConfig.lpszAutoConfigUrl != NULL )
{
fAutoProxy = TRUE;
autoProxyOptions.lpszAutoConfigUrl = ieProxyConfig.lpszAutoConfigUrl;
}
}
else
{
// use autoproxy
fAutoProxy = TRUE;
}
if( fAutoProxy )
{
if ( autoProxyOptions.lpszAutoConfigUrl != NULL )
{
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
}
else
{
autoProxyOptions.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
autoProxyOptions.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
}
// basic flags you almost always want
autoProxyOptions.fAutoLogonIfChallenged = TRUE;
// here we reset fAutoProxy in case an auto-proxy isn't actually
// configured for this url
fAutoProxy = WinHttpGetProxyForUrl( hiOpen, pwszUrl, &autoProxyOptions, &autoProxyInfo );
}
if ( fAutoProxy )
{
// set proxy options for libcurl based on autoProxyInfo
}
else
{
if( ieProxyConfig.lpszProxy != NULL )
{
// IE has an explicit proxy. set proxy options for libcurl here
// based on ieProxyConfig
//
// note that sometimes IE gives just a single or double colon
// for proxy or bypass list, which means "no proxy"
}
else
{
// there is no auto proxy and no manually configured proxy
}
}
Here is a complete code sample how to call WinHttpGetIEProxyConfigForCurrentUser method from winhttp.dll library in C#
[TestClass]
public class UnitTest1
{
[StructLayout(LayoutKind.Sequential)]
public struct WinhttpCurrentUserIeProxyConfig
{
[MarshalAs(UnmanagedType.Bool)]
public bool AutoDetect;
[MarshalAs(UnmanagedType.LPWStr)]
public string AutoConfigUrl;
[MarshalAs(UnmanagedType.LPWStr)]
public string Proxy;
[MarshalAs(UnmanagedType.LPWStr)]
public string ProxyBypass;
}
[DllImport("winhttp.dll", SetLastError = true)]
static extern bool WinHttpGetIEProxyConfigForCurrentUser(ref WinhttpCurrentUserIeProxyConfig pProxyConfig);
[TestMethod]
public void TestMethod1()
{
var config = new WinhttpCurrentUserIeProxyConfig();
WinHttpGetIEProxyConfigForCurrentUser(ref config);
Console.WriteLine(config.Proxy);
Console.WriteLine(config.AutoConfigUrl);
Console.WriteLine(config.AutoDetect);
Console.WriteLine(config.ProxyBypass);
}
}
There are registry keys for these values that you could get to directly of course. You could also do this in .NET without much hassle at all. I believe the WebClient object negotiates the proxy settings for you based on the current settings. This would look like this in C#:
using System.Net;
string url = "http://www.example.com";
WebClient client = new WebClient();
byte[] fileBuffer = client.DownloadFile(url);
Or something close to that.
For Firefox/Seamonkey, the problem is a bit more tricky because of the existence of many profiles.
If you want to assume there is only one profile then you just need to find prefs.js. You parse the network.proxy.type, and then use it to decide, which related values to read.
I'm working on some documents for mozilla, so put your followup questions in here (checked wiki box), and I'll try to give you the info you need.