Why do I need to call the ToList() method on my LINQ query?
For example:
private void btnEnc_Click(object sender, RoutedEventArgs e)
{
SHA1 sha = new SHA1Managed();
string sResult = "";
var v = sha.ComputeHash(
UTF8Encoding.Unicode.GetBytes(tbxWordToEncrypt.Text)
).Select(
p => sResult += string.Format("{0:x2}", p)
).ToList();
Clipboard.SetText(sResult);
tbxEncrypted.Text = sResult;
}
Also, when I try to access the clipboard I get a security dialog box. How can I prevent this?
By default you run under partial trust. When calling ClipBoard.SetText() (or ClipBoard.SetText(...)) the user must confirm access.
If you create an out-of-browser application and request elevated trust, this restriction no longer applies and no dialog box is shown.
You can configure your application to require elevated trust. You need to set this in the application's manifest.
For more information take a look at MSDN:
http://msdn.microsoft.com/en-us/library/ee721083(v=vs.95).aspx
Open your project's properties and navigate to the Silverlight tab.
Check the option "Enable running application out of browser".
Click on the button Out-Of-Browser Settings. A new dialog will popup.
Check the option "Require elevated trust when running outside the browser".
When a user installs your Silverlight application they will get a security warning before they can proceed. This only happens once. When running your application this way the ClipBoard.SetText() call will no longer trigger a security dialog.
The reason that you need to call to list is because the expression inside the Select isn't evaluated until the expression created by the LINQ statement is evaluated. Because you're using it to append to sResult, that variable won't have had its value changed before you put it on the clipboard unless you "run" the LINQ expression using ToList(). Note that the output of ToList() is basically worthless.
The bigger problem is that you're misusing the Select. You really should be using string.Join instead of building the string inside the Select clause. Building it inside the Select clause is going to be unexpected for people reading your code and harder to understand.
var sResult = string.Join( "",
sha.ComputeHash(
UTF8Encoding.Unicode.GetBytes(tbxWordToEncrypt.Text)
).Select(
p => string.Format("{0:x2}", p)
));
As for Linq:
You only need to call ToList() if you want the data to be evaluated imediatly.
Most Linq operators are lazy by design, and it's a good thing.
Related
I use LinqPad with the MySQL IQ driver to query data from a Magento database. I not only use this for reporting on the database but for doing updates. I can use the standard SubmitChanges() method to update data, but that often ends up with unbearably slow updates that can literally take hours - one of my tables has 35,707 records that I recreate on a regular basis.
So instead I generate SQL statements in my LinqPad queries and then execute them in a separate tab after selecting "SQL" in the language drop-down.
For example, my output might be something like this:
UPDATE catalog_category_product SET position = 6040 WHERE (category_id = 156 AND product_id = 12648);
UPDATE catalog_product_entity_media_gallery_value SET label = 'Sandy Beach' WHERE ((store_id = 0) AND (value_id = 8791));
-- Done.
I have recently found that LinqPad has a nice class called Hyperlinq that allows me to write code like this:
(new Hyperlinq(QueryLanguage.SQL, myGeneratedSqlText, "Run Query")).Dump();
The result is that a hyperlinq is put in the output window that will run the query (in my example the contents of myGeneratedSqlText) in a new tab and execute the query.
This is very convenient.
However, I now want to be able to save a log of queries that are executed. There doesn't seem to be (an easy) built-in way to manually execute a "generated" query in LinqPad. I can certainly use Util.Run to execute an existing saved query, in fact I do something like this:
Util
.OnDemand("Run Query", () =>
{
var fn = createOutputQueryFileName(); // Timestamped query name
System.IO.File.WriteAllText(fn, myGeneratedSqlText);
var run = Util.Run(fn, QueryResultFormat.Text);
var result = run.AsString();
return result.StartsWith("[]") ? "Success" : result;
})
.Dump();
The only drama with this is that I have to prefix the text in myGeneratedSqlText with the following:
var preamble = #"<Query Kind=""SQL"">
<Connection>
<ID>ec026b74-8d58-4214-b603-6d3145e03d7e</ID>
<Driver Assembly=""IQDriver"" PublicKeyToken=""5b59726538a49684"">IQDriver.IQDriver</Driver>
<Provider>Devart.Data.MySql</Provider>
<CustomCxString>[DELETED]</CustomCxString>
<Server>127.0.0.1</Server>
<Database>prod_1_8</Database>
<Password>[DELETED]</Password>
<UserName>[DELETED]</UserName>
<NoPluralization>true</NoPluralization>
<NoCapitalization>true</NoCapitalization>
<DisplayName>Production Tunnel</DisplayName>
<EncryptCustomCxString>true</EncryptCustomCxString>
<Persist>true</Persist>
<DriverData>
<StripUnderscores>false</StripUnderscores>
<QuietenAllCaps>false</QuietenAllCaps>
<Port>6606</Port>
</DriverData>
</Connection>
</Query>
";
I would really like to avoid all of this preamble stuff and include a line like this in my Util.OnDemand(...) code:
var run = Util.Run(QueryLanguage.SQL, myGeneratedSqlText, QueryResultFormat.Text);
(But this method doesn't exist.)
The key requirement here is to display a hyperlinq in the LinqPad output window that, if clicked, will save the query to disk as a log and also execute the query.
Can anyone suggest a clean way for me to do it?
I hope I've understood you correctly. When you've selected a connection in the top bar, your UserQuery becomes a datacontext. For this reason, you can use ExecuteQuery and ExecuteCommand on this within an action based Hyperlinq.
new Hyperlinq(() => {
"do log work here".Dump();
this.ExecuteQuery<string>(generatedSelect).Dump("Results");
this.ExecuteCommand(generatedCommand).Dump("Results");
}, "Run Query").Dump();
Unfortunately this outputs to the current tab, but hopefully this will at least get you most of the way to done :)
Here's an image of it at work:
As you're using MySQL, you can go via the connection property on this:
new Hyperlinq(() => {
"do log work here".Dump();
using (var command = this.Connection.CreateCommand())
{
// Usual command logic here
}
}, "Run Query").Dump();
I am working from the sample project here: http://www.codeproject.com/Articles/8086/Extending-the-save-file-dialog-class-in-NET
I have hidden the address/location bar at the top and made other modifications but I can't for the life of me manage to disable the button that lets you go up to the parent folder. Ist is in the ToolbarWindow32 class which is the problem. This is what I have at the moment but it is not working:
int parentFolderWindow = GetDlgItem(parent, 0x440);
//Doesn't work
//ShowWindow((IntPtr)parentFolderWindow, SW_HIDE);
//40961 gathered from Spy++ watching messages when clicking on the control
// doesn't work
//SendMessage(parentFolderWindow, TB_ENABLEBUTTON, 40961, 0);
// doesn't work
//SendMessage(parentFolderWindow, TB_SETSTATE, 40961, 0);
//Comes back as '{static}', am I working with the wrong control maybe?
GetClassName((IntPtr)parentFolderWindow, lpClassName, (int)nLength);
Alternatively, if they do use the parent folder button and go where I don't want them to, I'm able to look at the new directory they land in, is there a way I can force the navigation to go back?
Edit: Added screenshot
//Comes back as '{static}', am I working with the wrong control maybe?
You know you are using the wrong control, you expected to see "ToolbarWindow32" back. A very significant problem, a common one for Codeproject.com code, is that this code cannot work anymore as posted. Windows has changed too much since 2004. Vista was the first version since then that added a completely new set of shell dialogs, they are based on IFileDialog. Much improved over its predecessor, in particular customizing the dialog is a lot cleaner through the IFileDialogCustomize interface. Not actually what you want to do, and customizations do not include tinkering with the navigation bar.
The IFileDialogEvents interface delivers events, the one you are looking for is the OnFolderChanging event. Designed to stop the user from navigating away from the current folder, the thing you really want to do.
While this looks good on paper, I should caution you about actually trying to use these interfaces. A common problem with anything related to the Windows shell is that they only made it easy to use from C++. The COM interfaces are the "unfriendly" kind, interfaces based on IUnknown without a type library you can use the easily add a reference to your C# or VB.NET project. Microsoft published the "Vista bridge" to make these interfaces usable from C# as well, it looks like this. Yes, yuck. Double yuck when you discover you have to do this twice, this only works on later Windows versions and there's a strong hint that you are trying to do this on XP (judging from the control ID you found).
This is simply not something you want to have to support. Since the alternative is so simple, use the supported .NET FileOk event instead. A Winforms example:
private void SaveButton_Click(object sender, EventArgs e) {
string requiredDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
using (var dlg = new SaveFileDialog()) {
dlg.InitialDirectory = requiredDir;
dlg.FileOk += (s, cea) => {
string selectedDir = System.IO.Path.GetDirectoryName(dlg.FileName);
if (string.Compare(requiredDir, selectedDir, StringComparison.OrdinalIgnoreCase) != 0) {
string msg = string.Format("Sorry, you cannot save to this directory.\r\nPlease select '{0}' instead", requiredDir);
MessageBox.Show(msg, "Invalid folder selection");
cea.Cancel = true;
}
};
if (dlg.ShowDialog() == DialogResult.OK) {
// etc...
}
}
}
I don't this is going to work. Even if you disable the button they can type ..\ and click save and it will take them up one level. You can't exactly disable the file name text box and maintain the functionality of the dialog.
You'd be better off either using the FolderBrowserDialog and setting it's RootFolder property and asking the user to type the filename in or auto generating it.
If the folder you are wanting to restrict the users to isn't an Environment.SpecialFolder Then you'll need to do some work to make the call to SHBrowseForFolder Manually using ILCreateFromPath to get a PIDLIST_ABSOLUTE for your path to pass to the BROWSEINFO.pidlRoot
You can reflect FolderBrowserDialog.RunDialog to see how to make that call.
Since you want such custom behaviors instead of developing low level code (that is likely yo break in the next versions of windows) you can try to develop your file picker form.
Basically it is a simple treeview + list view. Microsoft has a walk-through .
It will take you half a day but once you have your custom form you can define all behaviors you need without tricks and limits.
I am trying to find a way to get back my previous variable's value so that I can resume my application to it's previous running state before it crashed when I MANUALLY relaunch it. I am currently using a 'config' file that is saved in the project folder. Is there a better way to do this?
Some small parts of my code that I want to save.
if (EventID == WIA.EventID.wiaEventItemCreated)
{
if (d != null)
{
foreach (Property p in d.Properties)
{
if (p.Name.Equals("Pictures Taken"))
Console.WriteLine("Taken");
}
wiaImageFile = (WIA.ImageFile)(d.Items[d.Items.Count].Transfer(FormatID.wiaFormatJPEG));
wiaImageFile.SaveFile(Properties.Settings.Default.FolderNameRaw + "\\" + imageCount + ".jpg");
imageCount++;//I want to save this count so that I can continue the sequence even after the application crashes
Pluck.Default.PhotoExistsInDirectory = true;
FacebookControls fbc = new FacebookControls();
if(Properties.Settings.Default.UseFB == true)
fbc.UploadPhotos();
}
}
A config file is a good answer in general. Your other options are usually the registry or the database, but I would argue that a config file is a safer option.
The thing about persisting this information is that it may cause an error again, and if so you'll want to be able to discard it easily. A file (of course stored in user settings space) is perhaps the way to do that. If need be you can instruct the user to delete the file. It's a more complicated fix for a user to access the registry or the database.
Also, you should wrap up your state in an appropriate object, and build initialization logic that initializes the state object and has mechanism for not loading for the config file.
I use config files. I also have a global exception handler that catches any exceptions and offers the chance to save any files (including those that the user is working on) before the app closes.
I would also agree with C Ross that you may persist the data that caused the app to fail. Another option that will not get you right back is to persist the settings at regular intervals using a timer or background process. I use this with several backups a bit like the system restore feature in windows.
You can handle UnhandledException, Application_ThreadException and Application.ApplicationExit Event, and try saving your data there:
http://www.switchonthecode.com/tutorials/csharp-tutorial-dealing-with-unhandled-exceptions
As #C. Ross said, user config file is a good choice.
Of course, first you'll have to preserve your application's state in some object during runtime.
As a preface, I've looked at every StackOverflow question matched by searching for this error (25 of them or so), and none of them seemed to address the problem I'm having.
I'm building up a PermissionsDialog that inherits from System.Windows.Form. Within the method that calls dialogPermissions.ShowDialog() I am retrieving some Role objects from the database and loading them into a couple of ListBoxes. That was working just fine, but now I need to override one of the properties of the Role objects I'm adding to the listboxes using this pseudocode process:
iterate over the List of Roles
look up a matching item out of a List of Profiles using List<T>.Find()
look up a property on the Profile
build up a new Role and set the Name property as needed
add the Role to a list of Roles for the PermissionsDialog
All of that goes smoothly, but when I call dialogPermissions.ShowDialog() the underlying framework code throws an AccessViolationException.
Here is what I believe to be the relevant code:
List<UserProfile> userProfiles = new List<UserProfile>();
List<Role> allRoles = new List<Role>();
dialogData.AllRoles = new List<Role>();
using (var objectContext = this.SiteContext.CreateObjectContext())
{
userProfiles = rs.UserProfiles.FindAll().ToList();
allRoles = rs.Roles.FindAll();
}
foreach (Role role in allRoles.Where(role => role.BuiltInId == (int)BuiltInRoleId.UserProfileRole)) {
var userProfile = userProfiles.Find(up => role.Id == up.Id);
var roleToAdd = new Role {
BuiltInId = role.BuiltInId,
Description = role.Description,
DirectoryEntry = role.DirectoryEntry,
Id = role.Id,
IsBuiltInRole = role.IsBuiltInRole,
Name = null != profile ? profile.DisplayName:role.Name
};
dialogData.AllRoles.Add(roleToAdd);
}
My suspicion is that this is somehow a deferred execution issue, but triggering execution by calling ToList() on dialogData.AllRoles before calling ShowDialog() doesn't resolve the issue. When I replace profile.DisplayName with a constant string I do not get the error.
Any clues what's going on under the covers here, or how to find out what's going on, or how to approach the problem differently so I can avoid it? All suggestions welcome ;-)
CONCLUSION
So here's the actual issue, I think:
Setting the Name property of the Role to null is just fine, but when the dialog tries to create a ListBoxItem out of the Role and uses the Role.Name property for the ListBoxItem's Content property (which is an Object), that can't be set as null and throws down in the framework code that's building up the dialog. Checking to make sure I had a value in there fixes the issue.
Seems like s strange exception to throw, but there you have it....
You test for profile != null, but don't test for profile.DisplayName != null so that's the first thing that comes to mind from just looking at your sample.
Standard exception finder is to go to Debug\Exceptions and check the box for break on thrown so you can see all the state when the exception is thrown.
You can stare at this code for a week and never find the reason for the AccessViolationException. Managed code does not die from processor faults like this one.
You'll need to dig out as much info you can get from the actual exception. That requires first of all that you enable unmanaged code debugging so that you can see the stack frames in the native code. Project + Properties, Debug tab, tick the "Enabled unmanaged code debugging" option.
Next, you want to make sure that you have .pdb file for any of the native Windows DLLs. Including the ones for Active Directory, somewhat suspect in this case. Tools + Options, Debugging, Symbols and enable the Microsoft Symbol Server. Press F1 if you have an older version of Visual Studio that doesn't make it a simple checkbox click.
Reproduce the crash, the call stack should give you a good hint what native code is suspect. Post it in your question if you can't make hay of it.
I have an application which writes HTML to a WebBrowser control in a .NET winforms application.
I want to detect somehow programatically if the Internet Settings have Javascript (or Active Scripting rather) disabled.
I'm guessing you need to use something like WMI to query the IE Security Settings.
EDIT #1: It's important I know if javascript is enabled prior to displaying the HTML so solutions which modify the DOM to display a warning or that use tags are not applicable in my particular case. In my case, if javascript isn't available i'll display content in a native RichTextBox instead and I also want to report whether JS is enabled back to the server application so I can tell the admin who sends alerts that 5% or 75% of users have JS enabled or not.
Thanks to #Kickaha's suggestion. Here's a simple method which checks the registry to see if it's set. Probably some cases where this could throw an exception so be sure to handle them.
const string DWORD_FOR_ACTIVE_SCRIPTING = "1400";
const string VALUE_FOR_DISABLED = "3";
const string VALUE_FOR_ENABLED = "0";
public static bool IsJavascriptEnabled( )
{
bool retVal = true;
//get the registry key for Zone 3(Internet Zone)
Microsoft.Win32.RegistryKey key = Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3", true);
if (key != null)
{
Object value = key.GetValue(DWORD_FOR_ACTIVE_SCRIPTING, VALUE_FOR_ENABLED);
if( value.ToString().Equals(VALUE_FOR_DISABLED) )
{
retVal = false;
}
}
return retVal;
}
Note: in the interest of keep this code sample short (and because I only cared about the Internet Zone) - this method only checks the internet zone. You can modify the 3 at end of OpenSubKey line to change the zone.
If you are having troubles with popups popping up, i've included a solution for you, and if you want to disable/enable javascript on th client machine (or even just read/query if it is enabled/disabled) ive included that answer for you as well, here we go:
Which popup message do you want to disable? If it's the alert message, try this, obviously resolving the window or frame object to your particular needs, I’ve just assumed top-level document, but if you need an iframe you can access it using window.frames(0). for the first frame and so on... (re the JavaScript part)... here is some code, assuming WB is your webbrowser control...
WB.Document.parentWindow.execScript "window.alert = function () { };", "JScript"
You must run the above code only after the entire page is done loading, i understand this is very difficult to do (and a full-proof version hasn't been published yet) however I have been doing it (full proof) for some time now, and you can gather hints on how to do this accurately if you read some of my previous answers labelled "webbrowser" and "webbrowser-control", but getting back to the question at hand, if you want to cancel the .confirm JavaScript message, just replace window.alert with window.confirm (of course, qualifying your window. object with the correct object to reach the document hierarchy you are working with). You can also disable the .print method with the above technique and the new IE9 .prompt method as well.
If you want to disable JavaScript entirely, you can use the registry to do this, and you must make the registry change before the webbrowser control loads into memory, and every time you change it (on & off) you must reload the webbrowser control out and into memory (or just restart your application).
The registry key is \HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\ - the keyname is 1400 and the value to disable it is 3, and to enable it is 0.
Of course, because there are 5 zones under the Zones key, you need to either change it for the active zone or for all zones to be sure. However, you really don't need to do this if all you want to do is supress js dialog popup messages.
Let me know how you go, and if I can help further.
Here is a suggestion - Encode the warning into your webpage as default. Create a javascript that runs on page load which removes that element. The warning will be there when ever javascript is not allowed to run.
It's a long while since I coded client side HTML javascript to interact with the DOM so I may be a little out of date. i.e. you will need to fix details, but I hope I get the general idea across.
<script>
document.getElemntByID("noJavascriptWarning").innerHTML="";
</script>
and in your HTML body
<DIV id="noJavascriptWarning" name="noJavaScriptWarning">Please enable Javascript</DIV>