Excel Range.Find and maintaining user selected find options - visual-studio-2010

When automating excel using the Excel Interop API, I can easily do a range search using the method Range.Find. I am passing through the LookIn, LookAt, SearchOrder, SearchDirection, and MatchCase options for the Find. This as noted by the MSDN documentation, persists the values passed into this method into the user settings, so the next time that the user opens the find form, the options will be selected which I used in the Range.Find method.
I need to persist the values of the find options before and after I do the programmatic find. So I want to capture the current find options, then do the Range.Find, and then set the find options back to the options that were set before my search. However, I do not see that the find options are publicly accessible. Any ideas on how to get these?
I'm basically looking to retrieve current find option values for LookIn, LookAt, SearchOrder, SearchDirection, and MatchCase.
Update
The most interesting thing I could find so far is that you can access the Excel Application dialogs - Dialogs Interface. So here, I can get access to the FormulaFind dialog, which is slightly different than the Find and Replace dialog, though may lead to some of the properties I'm looking for. I haven't had any luck, but perhaps there's a way to access the properties through this form using reflection. I'll keep trying something with this.
// xlDialogFormulaFind, xlDialogFormulaReplace
Excel.Dialog dialog = this.Application.Dialogs.Item[Excel.XlBuiltInDialog.xlDialogFormulaFind];

Well, I am not sure if you'd consider this approach, but I'll give a shot here in case it might be helpful.
What I would do is, I'd create a registry key holding the values you wanted to persist. I could then call RegistryKey.GetValue(valuename) to retrieve values, provided that there's no exceptions thrown.
As long as that registry key stays there, unchanged, and you have enough privilege to access registry key, you should be able to always get the same values.
Wish we could really use application settings here, which would make it easier, but, well, as you might have known, vsto add-in doesn't like it, according to this article.
You cannot use application settings in an unmanaged application that
hosts the .NET Framework. Settings will not work in such environments
as Visual Studio add-ins, C++ for Microsoft Office, control hosting in
Internet Explorer, or Microsoft Outlook add-ins and projects.
Hope this helps.

Related

Allow selection in Explorer-style list view to start in the first column

In Windows 7's Windows Explorer list view (what allegedly is not list view at all) in the Details view, you can start selection marquee in the first (Name) column. You just need to start outside the actual name.
The same is true for default-style list view control in Details view.
But if you set the list view control to the Explorer style (using the SetWindowTheme), what should mimic the Windows Explorer, this does not work anymore. You can start selection in the second and later columns only.
SetWindowTheme(listView1.Handle, "explorer", null);
Is there any way to make list view mimic the Explorer selection style?
I suppose there's no settings to enable such behavior and this would have to be coded. Like handling the mouse down and triggering selection. But I have no idea how to do that.
Thanks.
Ntb, I'm using C++Builder, but this should be purely Win32 issue. I've tested this with WinForms too (hence the C# sample above).
Is there any way to make list view it mimic the Explorer selection style?
No, SysListView32 in explorer theme does not behave that way. The control used by the modern Explorer is actually DirectUIHwnd. And you are not able to use one of them.
The only way to get the behaviour of DirectUIHwnd is to code it yourself. I expect that's possible to do but I'd also expect it to be very difficult to achieve.
Actually there is a way to mimic Explorer selection behavior. It requires a lot of additional declarative work, but it is possible.
You need to get undocumented IListView interface via undocumented LVM_QUERYINTERFACE message (note that interface declaration and GUIDs are different for Windows Vista and Windows 7+). Details about constants and declarations can be found here:
IListView at Geoff Chappell - Software Analyst or
Undocumented List View Features at Code Project.
After acquiring the interface all you need is simply a call to SetSelectionFlags(1, 1) method. Voila you are done.

How to get ONLY w3wp instances when specifying performance counters for Perfmon/LogMan on Windows?

Hopefully this question has a simple answer i'm overlooking! I have an IIS webserver with multiple sites on it. In Perfmon, they show up as w3wp#1, w3wp#2, etc... I'm writing a Logman script that will collect performance counter data using the counters/instances that I specify and I want to ONLY collect any w3wp worker processes.
I've tried a couple ways, but no luck:
\.NET CLR Memory(*w3wp*)\
\.NET CLR Memory(w3wp#*)\
\.NET CLR Memory(w3wp*)\
I've looked at the documentation here, and it seems like it claims to support wildcards, but not partial matches. I'm not sure what to make of that. Is there any way accomplish what I want? Hope I explained this well enough. Let me know if more details are needed.
Thanks!
There is a way to display the instance by appending Process Id to it. Since ProcessId do not change it helps determining the correct instance. This post describes the method - Perfmon: Identifying processes by PID instead of instance.
Relevant part from the link:
Making below registry change will display processes in the format of **ProcessName_PID** instead of **ProcessName#1**.
Click Start, click Run, type regedit, and then click OK.
Locate and then click the following registry subkey:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PerfProc\Performance
On the Edit menu, click New, and then click DWORD Value.
Right-click New Value #1, click Rename, and then type ProcessNameFormat to name the new value.
Right-click ProcessNameFormat, and then click Modify.
In the Data value box, type one of the following values, and then click OK:
1: Disables PID data. This value is the default value.
2: Enables PID data.
Exit Registry Editor.
Warning: Serious problems might occur if you modify the registry incorrectly by using Registry Editor or by using another method. These problems might require that you reinstall the operating system. Microsoft cannot guarantee that these problems can be solved. Modify the registry at your own risk.
Important: If you enable this feature, you may be unable to monitor process-specific information by using third-party utilities or custom-made programs, and this functionality may change at any time in the future without notice.
Hope it helps someone.
I came up with a custom batch script that find the application pool ID, PID, and associates it with the IIS worker process in question. From there, I can manually FIND and REPLACE a generic placeholder in my perfmon configuration file to start collecting for the specific site(s). I can supply some details if there is interest.

How can I get the name of a Visual Basic control given its HWND?

I'm working on a little macro record/replay tool which can automate a few very old Visual Basic 6 GUIs we have. To do so, I'm identifying the controls by their name (the value of the name property of a control, that is).
One part of this tool needs to determine the name of a control given its HWND. For newer Visual Basic applications which were done using VB.NET, I can use the WM_GETCONTROLNAME window message. This works nicely.
However, this message is not understood by older windows. Is there any way to do this for controls of Visual Basic 6 applications? A solution which does not require being in the process of the GUI would be preferrable, but if I had a solution which only works inside the GUI process then that would be acceptable as well (since I can do the injection myself).
UPDATE: One thing I just tried, this moderate success: I used the AccessibleObjectFromWindow to check for implementations of the IAccessible interface of the object which shows the given HWND. In case I get an implementation (it seems that many [all?] Visual Basic controls implement this interface), I use the accName property to read out the "accessible name". Sometimes this does yield a useful string, but usually it doesn't.
I believe the only way would be getting inside the process and obtaining a pointer to the Form object, yet I have no idea how to do it from outside.
Is it possible you add support for the WM_GETCONTROLNAME to those older applications?
Or maybe, you could identify the controls by some other, natively-available properties?
Other that that, as Raymond is saying, there isn't much you can do.
Can you modify the vb6 apps? if so in each form load event you could iterate me.controls and use the SetProp(ctrl.hwnd, "MYNAME:" & ctrl.name, 0) api to add the name to the window's own property list, then in your other app you can EnumProps(ctrl_HWND) looking for the one that begins with MYNAME: and parse out the value.

Does a Win32 control's control ID change with each run?

In other words, can I count on a control ID as a reliable identifier?
From some reading I've done, it sounds like .NET controls can have control IDs that change with every run, is this so for Win32 apps as well, or are they something that's hardcoded in the source?
The window/control in question is actually an Internet Explorer dialog if that helps.
In general win32 dialog resource IDs do not change when you run the app. However, they are internal implementation details and as such they are subject to change whenever an update (patch, service pack, major release) to the application is made.
In general all of IE's dialogs use hard-coded control IDs. There may be some that are dynamic. If you give the specific control I might be able to give you a better answer.
The answer is "it depends on the circumstances, but in the majority of programs, these will not change across multiple executions." In general, a control ID or resource ID will be the same across every execution of the same program.
In most implementations, resources are stored in the resource section of the PE executable and are assigned a resource ID within that data structure. Usually, the developer specifies the resource in a .rc file.
The exceptional case is via APIs such as CreateDialogIndirect() which allow IDs specified through the API at runtime. Such dynamic creation is uncommon, however. Consistency of resource IDs and control IDs is the expected condition, so even in the case of the CreateXXXIndirect() API, users of the API would be ill-advised to chose a varying ID.
Microsoft has spent years trying to deal with applications which embed assumptions about internal windows implementation details. One of the biggest causes of compatibility problems for IE8 was caused by applications which made assumptions about the window order of IE controls. When the UI was changed in IE8, the controls moved and a number of browser plugins broke hideously.
In general you should never ever make assumptions about controls in an application that you didn't write - your code WILL break in the future (not might break, will break).
As a general rule, no they don't change between runs. Control IDs are usually specified with a dialog template, and that's a static resource compiled into an .exe or .dll. Controls can also be created using a regular call to CreateWindow or CreateWindowEx. In such cases, the ID is usually a constant, but it could be anything in principal (even a random value).
In any case, if you're planning to muck around with a dialog in another application, then you are asking for trouble. Control IDs can and do change between different versions of a program.
It depends on the control. Controls that are dynamically created could have a different ID every time they are created. Controls based on static dialog resources will have static IDs.
Even if a dialog is backed by a dialog resource template, controls can be added dynamically at runtime and those controls could have dynamically generated IDs.
Depending on your intent, it may be acceptable to store and reuse it for future lookups or traces; but in general it isn't safe.
If the window is based upon a dialog template, items declared in the template generally don't change. It is perfectly safe under typical circumstances to use these as identifiers.
Sometimes the window class name or a portion of it can be used as an identifier instead, depending on the window host.
If the dialog is one of the standard prompts from internet explorer, you may want to use text stored in adjacent controls or the dialog caption as additional verification info (if localized versions of IE are not an issue). If the dialog is a window that embeds an instance of MSHTML/IE; none of these options may be viable- but you can use OLE accessibility to get at the document shown and then browse the DOM from there.

How to start/stop/pause the windows search indexer

I'd like to determine how to programatically start/stop/pause the indexer from Microsoft Search.
I know it is possible because I've seen it done in programs like this one: http://brandontools.com/files/folders/sidebar_gadgets/entry511.aspx
However, I cannot find any docs on MSDN or anywhere.
There is a "Windows Search" service which can be controlled with traditional service control methods. However, starting/stopping this service also changes the availability of search itself. I want to control just the indexer.
Does anyone know where docs may be found that describe how to interact with the indexer? My search skills have failed me.
There isn't a way to simply disable the indexing part. It's an all or nothing service. The description of the WSearch service states:
"Provides content indexing and property caching for file, email and other content (via extensibility APIs). The service responds to file and email notifications to index modified content. If the service is stopped or disabled, the Explorer will not be able to display virtual folder views of items, and search in the Explorer will fall back to item-by-item slow search."
However, you might be able to control it through drive/folder properties ... from Explorer, you can switch it of for an individual drive (see the properties of a drive; there's an option "allow indexing service..."), or for a folder (folder properties -> advanced -> "For fast searching, allow indexing service...").
EDIT ... a bit of googling, and the above properties are available - if you look at the MSDN page for System.IO.FileAttributes, there's a property NotContentIndexed with the description The file will not be indexed by the operating system's content indexing service. I would assume that you should be able to set this on individual folders. I don't know if this works if set at the drive level (without a recursive run through the drive), but hopefully it'll give you a head-start on whatever you're ultimately trying to achieve.
According the Microsoft there isn't an official way of doing so.
Here is a great tutorial on programmatically interacting with Windows Search: article at JoyOfCode.
The Windows Search 3.x SDK provides a .NET API that works against Windows Search 3 or 4.
Unfortunately, it doesn't expose pause/resume. All of the index control samples I have found use WMI to stop the search service. That will stop indexing, obviously, but at the expense of search itself not being available.
It's an old thread, but I ran across it. Someone else might as well.
Use an AutoIT script to open the Indexing Options and click the Pause button in the dialog box.
Something like this:
ServiceController service = new ServiceController("WSearch");
service.Start();
or
service.Stop();
Open the "Run" Dialog (Start | Run), type(or copy)
%SystemRoot%\system32\compmgmt.msc /s
and unfold the last one

Resources