How can I get all keys in System.Collections.Specialized.HybridDictionary? - visual-studio-2010

How can I get all keys in System.Collections.Specialized.HybridDictionary without using foreach?
I have a method
void Get(IDictionary options)
{
...
}
And while debugging I can set up a breakpoints inside a body of this method. I want to see all keys of options in the watch window in Visual Studio 2010.

There's a property Keys, are you looking for that?
var allKeys = dict.Keys;
MSDN
Gets an ICollection containing the keys in the HybridDictionary.
The order of the values in the ICollection is unspecified, but it is
the same order as the associated values in the ICollection returned by
the Values method.
Retrieving the value of this property is an O(1) operation.
If you instead want to access it like a List(what is not necessarily a good idea as you can see from the remark section of msdn quoted above):
var allKeys = new List<object>(dict.Keys.Count);
allKeys.AddRange(dict.Keys.Cast<object>());
(which uses a loop implicitely anyway)
Edit:
Actually I need to see all keys in the watch window while debugging in
Visual Studio 2010. I can't use foreach and List in the watch window.
Then execute this in the quick-watch-window:
string.Join("," , dict.Keys.Cast<object>());

Related

macOS command line app - User Defaults dictionaryRepresentation shows too many values

I a developing a macOS commandline application in Xcode, which uses User Defaults. I have the following code for my User Defaults
if let configDefaults = UserDefaults.init(suiteName: "com.tests.configuration") {
configDefaults.set("myStringValue", forKey: "stringKey")
configDefaults.synchronize()
print(configDefaults.dictionaryRepresentation())
}
This will create my own .plist file in the ~/Library/Preferences folder. If I look into the file, I can see only my single value which I added, which is perfectly fine. But when I call dictionaryRepresentation() on my UserDefaults object, the there are a lot of other attributes (I guess from the shared UserDefaults object), like
com.apple.trackpad.twoFingerFromRightEdgeSwipeGesture or AKLastEmailListRequestDateKey
Looking into the documentation of UserDefaults, it seems that this has to do with the search list of UserDefaults and that the standard object is in the search list:
func dictionaryRepresentation() -> [String : Any]
Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.
There are also the methods addSuite and removeSuite for a UserDefaults object, so I am guessing I need to remove the .standard suite from my configDefaults object, but I don't know the name, which should be used for that in the method.
Is it possible to remove the .standard defaults from the dictionary representation? I basically just want all of my own data in a dictionary, nothing more.
The reason I am trying to get only my values from the UserDefaults, is that a have a number of object of a custom type Connection (which store the configuration to connect to a server), which are saved in the UserDefaults. On program start I want to be able to load all objects into my app. Therefore I thought I could use dictionaryRepresentation(), as it would return all elements in the UserDefaults. But then there should be only my Connection objects in the dictionary, so that I can cast it to [String: Connection].
Given your purpose (in your latest edit of your question), what you should do is store a collection of Connection objects under a single key. Then, look up that key to get the collection.
It's not clear if the collection should be an array of Connection objects or a dictionary mapping strings to Connections. That's a choice you can make.
But, in any case, you shouldn't rely on the defaults being empty of everything else.
In other words, you would do:
UserDefaults.standard.set(yourStringToConnectionDictionary, forKey:"yourSingleKey")
and later:
let connectionMap = UserDefaults.dictionary(forKey:"yourSingleKey")
then look up Connections in the connectionMap by their name/ID/whatever.
Though the other solution proposed by Ken Thomases may be better from a design standpoint, I've found a solution that does exactly what I initially wanted. Calling
UserDefaults.standard.persistentDomain(forName: "com.company.TestApp.configuration")
Returns a dictionary containing only the values I've added to the domain com.company.TestApp.configuration, using
let configs = UserDefaults.init(suiteName: "com.company.TestApp.configuration")!
configs.set(someData, forKey: someKey)
Strangely in the Apple documentation says this about persistentDomain(forName:):
Calling this method is equivalent to initializing a user defaults object with init(suiteName:) passing domainName and calling the dictionaryRepresentation() method on it.
But this is not the case (see my question). Clarification on that subject is more than welcome.

retrieving data from arbitrary memory addresses using VSIX

I am working on developing a debugger plugin for visual studio using VSIX. My problem is I have an array of addresses but I cannot set the IDebugMemoryBytes2 to a particular address. I use DEBUG_PROPERTY_INFO and get the array of addresses, and I also am able to set the context to the particular addresses in the array using the Add function in IDebugMemoryContext2. However, I need to use the ReadAt function to retrieve n bytes from a specified address (from IDebugMemoryBytes2).
Does anyone have any idea how to retrieve data from arbitrary addresses from memory?
I am adding more information on the same:
I am using the Microsoft Visual Studio Extensibility package to build my debugger plugin. In the application I am trying to debug using this plugin, there is a double pointer and I need to read those values to process them further in my plugin. For this, there is no way to display all the pointer variables in the watch window and hence, I am not able to get the DEBUG_PROPERTY_INFO for all the block of arrays which the pointer variable is pointing to. This is my problem which I am trying to address. There is no way for me to read the memory pointed to by this double pointer.
Now as for the events in the debuggee process, since the plugin is for debugging variables, I put a breakpoint at a place where I know this pointer is populated and then come back to the plugin for further evaluation.
As a start, I was somehow able to get the starting addresses of each of the array. But still, I am not able to read x bytes of memory from each of these starting addresses.
ie., for example, if I have int **ptr = // pointing to something
I have the addresses present in ptr[0], ptr[1], ptr[2], etc. But I need to go to each of these addresses and fetch the memory block they are pointing to.
For this, after much search, I found this link: https://macropolygon.wordpress.com/2012/12/16/evaluating-debugged-process-memory-in-a-visual-studio-extension/ which seems to address exactly my issue.
So to use expression evaluator functions, I need an IDebugStackFrame2 object to get the ExpressionContext. To get this object, I need to register to events in the debuggee process which is for breakpoint. As said in the post, I did:
public int Event(IDebugEngine2 engine, IDebugProcess2 process,
IDebugProgram2 program, IDebugThread2 thread, IDebugEvent2
debugEvent, ref Guid riidEvent, uint attributes)
{
if (debugEvent is IDebugBreakpointEvent2)
{
this.thread = thread;
}
return VSConstants.S_OK;
}
And my registration is like:
private void GetCurrentThread()
{
uint cookie;
DBGMODE[] modeArray = new DBGMODE[1];
// Get the Debugger service.
debugService = Package.GetGlobalService(typeof(SVsShellDebugger)) as
IVsDebugger;
if (debugService != null)
{
// Register for debug events.
// Assumes the current class implements IDebugEventCallback2.
debugService.AdviseDebuggerEvents(this, out cookie);
debugService.AdviseDebugEventCallback(this);
debugService.GetMode(modeArray);
modeArray[0] = modeArray[0] & ~DBGMODE.DBGMODE_EncMask;
if (modeArray[0] == DBGMODE.DBGMODE_Break)
{
GetCurrentStackFrame();
}
}
}
But this doesn't seem to invoke the Event function at all and hence, I am not sure how to get the IDebugThread2 object.
I also tried the other way suggested in the same post:
namespace Microsoft.VisualStudio.Debugger.Interop.Internal
{
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("1DA40549-8CCC-48CF-B99B-FC22FE3AFEDF")]
public interface IDebuggerInternal11 {
[DispId(0x6001001f)]
IDebugThread2 CurrentThread { [return:
MarshalAs(UnmanagedType.Interface)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)]
get; [param: In, MarshalAs(UnmanagedType.Interface)]
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType =
MethodCodeType.Runtime)] set; }
}
}
private void GetCurrentThread()
{
debugService = Package.GetGlobalService(typeof(SVsShellDebugger)) as IVsDebugger;
if (debugService != null)
{
IDebuggerInternal11 debuggerServiceInternal =
(IDebuggerInternal11)debugService;
thread = debuggerServiceInternal.CurrentThread;
GetCurrentStackFrame();
}
}
But in this method, I think I am missing something but I am not sure what, because after the execution of the line
IDebuggerInternal11 debuggerServiceInternal =
(IDebuggerInternal11)debugService;
when I check the values of the debuggerServiceInternal variable, I see there is a System.Security.SecurityException for CurrentThread, CurrentStackFrame (and so obviously the next line causes a crash). For this, I googled the error and found I was missing the ComImport attribute to the class. So I added that and now, I get a System.AccessViolationException : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
I am new to C# programming as well and hence, it is a bit difficult to grasp many things in short duration. I am lost as to how to proceed further now.
Any help in the same or suggestions to try another way to achieve my objective will be greatly appreciated.
Thanks a lot,
Esash
After much search, since I am short of time, I need a quick solution and hence, for now, it seems like the quickest way to solve this problem is to hack the .natvis files by making it display all the elements of the pointer and then using the same old way by using IDebug* interface methods to access and retrieve the memory context for each of the pointer elements. But, after posting the same question in msdn forums, I think the proper answer to this problem is as mentioned by Greggs:
"For reading memory, if you want a fast way to do this, you just want the raw memory, and the debug engine of the target is the normal Visual Studio native engine (in other words, you aren't creating your own debug engine), I would recommend referencing Microsoft.VisualStudio.Debugger.Engine. You can then use DkmStackFrame.ExtractFromDTEObject to get the DkmStackFrame object. This will give you the DkmProcess object and you can call DkmProcess.ReadMemory to read memory from the target."
Now, after trying a lot to understand how to implement this, I found that you could just accomplish this using :
DkmProcess.GetProcesses() and doing a ReadMemory on the process returned.
There is a question now, what if more than one processes are returned. Well, I tried attaching many processes to the current debugging process and tried attaching many processes to the debuggee process as well, but found that the DkmProcess.GetProcesses() gets only the one from which I regained the control from, and not the other processes I am attached to. I am not sure if this will work in all cases but for me, it worked this way and for anyone who has similar requirements, this might work as well.
Using the .natvis files to accomplish this means, using IndexListItems for VS2013 and prior versions, and using CustomListItems for VS2015 and greater versions, and to make it look prettier, use the "no-derived" attribute. There is no way to make the Synthetic tag display only the base address of each variable and hence, the above attribute is the best way to go about, but this is not available in VS2013 and prior versions (The base address might get displayed but for people who want to go beyond just displaying contents and also access the memory context of the pointer element, Synthetic tag is not the right thing).
I hope this helps some developer who struggled like me using IDebug* interfaces. For reference, I am also giving the link to the msdn forum where my question was answered.
https://social.msdn.microsoft.com/Forums/en-US/030cef1c-ee79-46e9-8e40-bfc59f14cc34/how-can-i-send-a-custom-debug-event-to-my-idebugeventcallback2-handler?forum=vsdebug
Thanks.

Typescript Window Setting Variable

I have part of typescript code
var root = window['appPath']
window.location.replace(root + '.... some url
Is the variable windows part of typescript? How do I assign it? Is it a key/value and what can I store in it?
Thanks
Is the variable windows part of typescript
Its a part of browser spec : http://www.w3schools.com/jsref/obj_window.asp
TypeScript defines these common globals for you in a file lib.d.ts : https://github.com/Microsoft/TypeScript/blob/master/bin/lib.d.ts
How do I assign it?
You shouldn't and actually browsers will not let you.
Is it a key/value and what can I store in it?
All JavaScript objects (I'm being lose here) act like key/value stores. The only allowed key is string. Value can be any other JavaScript object.
That said. DONT PUT STUFF ON WINDOW. MILLIONS OF KITTENS WILL DIE

retrieve the Quote Detail with c#

I'm trying to create a custom workflow (for Dynamics CRM 2011) which must send an email with information on the Details Quote from a quote.
I create it in Visual Studio 2010 with the sdk.
The workflow is triggered manualy from a quote.
I am able to retrieve the value of the customerid, but I am unable to get the attached documents or the quotedetails of the Quote, when I launched the workflow I have this exception :
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Microsoft.Xrm.Sdk.Entity.get_Item(String attributeName)
at CPageCRM.Workflow.QuoteSendMailNotificationRIP.Execute(CodeActivityContext executionContext)
My code is :
//to get the current Quote
Entity preImageEntity = context.PreEntityImages.Values.FirstOrDefault();
//preImageEntity is a Quote because I trigger the workflow from a Quote
//the next two lines work, I can retrieve the good value of the Quote
string natureDevis = Utils.GetOptionSetValueLabel(service, preImageEntity, "new_nature", (OptionSetValue)preImageEntity["new_nature"]);
string prospectDevis = ((EntityReference)preImageEntity["customerid"]).Name;
//I get the exception after that :
List<QuoteDetail> listQuoteDetail = new List<QuoteDetail>();
listQuoteDetail = preImageEntity["quote_details"] as List<QuoteDetail>; //I get the exception
I don't understand why the quote_details doesn't exist in the dictionnary, because when I do :
Quote devis = new Quote();
devis.quote_details //<= (the autocompletion is working)
I have the same problem when I try to get sharepointdocumentlocation
Anyone have an explication? How can I retrieve the Quote Details and the document attached to my Quote from the code?
Thanks
A comment and potential answer.
My comment is when retrieving stuff out of the Images I often find it easier to let the compiler grab the proper type and just use 'var'.
My answer is that quote_details isn't just a field, but an actual 1-n relationshp (by looking in the metadata browser). You may need to get the related entities in a separate retrieve.
Edit:
For example: _service.Retrieve("quote", quoteId, new ColumnSet("quote_details"))
will retrieve the quote details from the service. However, you could also check and see if you are passing in the quote_details attribute from the PreImage.
I successed with a linq query
I had to search the quote_detail which were linked to the quote :
var queryQuoteDetail = from r in orgServiceContext.CreateQuery("quotedetail")
where ((EntityReference)r["quoteid"]).Id.Equals(context.PrimaryEntityId)
select r;

How do I swap items in a VB6 collection?

If I have a collection of forms (myForms) and I want to switch the position of two forms in the collection (say items 3 and 4 for example), I would expect that the following code would work:
Dim temp as Form
Set temp = myForms(3)
Set myForms(3) = myForms(4)
Set myForms(4) = temp
But that doesn't work. It fails at the third line with the error "Controls property is read only." If I change the line to:
myForms(3) = myForms(4)
I get a type mismatch error instead.
If myForms is a standard collection:
Dim myForms as New Collection
(which is actually different from the controls collection) and you've added the forms using:
myForms.Add frmOne, myForms.Add frmTwo
etc then (yes) you do need to use the Add and Remove methods because of the way the collection references the added objects.
Otherwise the interpretation is that you actually want to replace one form with another and this is not allowed. You can't say:
Set frmOne = frmTwo
unless these are actually variables of type Form.
Why do you need to switch the order? Are you referencing the item numbers somewhere? Would using a Dictionary to collect the forms and reference them by a key be useful?
PS. The type mismatch is simply because both items are objects and need to be 'Set'.
You can't actually swap around items in the controls collection in VB6. You need to use the Add and Remove functions associated with each. Check out this article:
http://support.microsoft.com/kb/190670
Hope this helps!

Resources