How programatically disable specific item in network connection properties? - delphi

I want to know if some API/code exists to disable a specific item in the (current) network connection properties?
If yes, could you show a working code example, explain the details, and point out some limitations (if they exist) of the technique used?

The API to disable these bindings is INetCfgBindingPath::Enable. The bindview sample illustrates how to call the API.
From Windows 8 and later, you may alternatively invoke the WMI method /root/standardcimv2/MSFT_NetAdapterBindingSettingData::Disable. Here's a line of PowerShell that illustrates how to disable the bindings from a NIC named "mb-port" to the "ms_msclient" driver (aka wkssvc):
Get-CimInstance -Namespace root/standardcimv2 -Query 'SELECT * FROM MSFT_NetAdapterBindingSettingData WHERE Name = "mb-port" AND ComponentID = "ms_msclient"' | Invoke-CimMethod -MethodName Disable
Note that the GUI is being sneaky: it merges multiple bindpaths into the same checkbox. In the example you have highlighted, there are likely 2 bindpaths from ms_msclient to the NIC: one over IPv4 and one over IPv6. The GUI disables/enables all paths when you clear/tick the checkbox. If you come in through the API and want to do the same, you'll need to enumerate all bindpaths that start from ms_msclient and go to the NIC mb-port.

Related

Delphi TurboPower Async Professional Data Packet Access Violation…

I use windows 7, 64-bit SP1, and TP Async V4.07 and have the following problem:
I have two Com ports, Com11, and Com18.
I add the following components to my form:
I open a Com port on ApdComPort2 (Com18) and it works without a problem. The ApdDataPacket2 detects the packet terminator and the result displayed is what is expected. Both Com11 and Com18 work fine.
Now if I open another Com port (Com11) with ApdComPort1 I get an Access violation:
The code that generates the error is this in the AdPacket module:
procedure TApdDataPacketManager.EnablePackets;
var
i : integer;
begin
for i := 0 to pred(PacketList.Count) do
with TApdDataPacket(PacketList[i]) do
if Enabled then
Enable;
end;
It is the PacketList.Count that seems to be the problem when it iterates through the list but I can’t catch why:
Note that ApdComPort2 works without problem with both Com11 and Com18.
If I remove the Apd2 components then Apd1 works as expected. The problems surface when I try to use two (or more) Apd components at the same time.
Does anybody have a suggestion or can recommend a component that works with more than one serial port simultaneously?
Some notes about the Turbo Power Async Professional components:
When using the Async components it is very important on how you add the components to the form. If you don’t does it in the right order and in the correct way it will not work if you use more than one serial port. You will actually get an access violation. For example, if you add the components below you have to do it in this way:
Add one ApdComPort to the form, it will become ApdComPort1
Now copy and paste this component to the form, it will become ApdComPort2
Add one ApdDataPacket component to the form, it will become ApdDataPacket1
Now copy and paste this component to the form, it will become ApdDataPacket2
Add one ApdSLController component to the form, it will become ApdSLController1
Now copy and paste this component to the form, it will become ApdSLController2
When doing it, as described above, it works to use two serial ports with ApdDatapacket. Now I don’t get any getting Access violations. I have tested it up to 4 ports and it works as well.

TSaveDialog Options ofAllowMultiSelect doesn't work properly on a W10 system

I have an old application, untouched for a long time, built with C++ Builder 2009, that still works fine.
That is to say ..
Today I noticed some of the TSaveDialog->Options don't work as intended on my Windows 10 system. To make sure I'm not dreaming I tested the same application on an older Windows version (I tried XP) and there it worked perfectly fine as intended.
The TSaveDialog instance is setup at design time with Options: [ofHideReadOnly,ofAllowMultiSelect,ofEnableSizing]
I noticed today (on Windows 10) that ofAllowMultiSelect doesn't work anymore ?
Instead ofOverwritePrompt is (incorrectly) used !
In other words I cannot select two ore more files anymore and when I select a file that already exists I first get a 'Confirm Save As' dialog.
When I compile again on my Windows 10 system, using C++ Builder 2009, in debug mode and inspect Options, the debugger seems to (still) properly see ofHideReadOnly, ofAllowMultiSelect, ofEnableSizing, yet the problem persists. So it's not as if the values changed somehow ?
When I try at runtime:
SaveDialog->Options.Clear() ;
SaveDialog->Options << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect ;
the problem also persists !
When I remove ofAllowMultiSelect (at run time or at design time) 'Confirm Save As' is not shown anymore on an existing file (but I obviously also still can't select multiple files).
I'm flabbergasted by this to be honest ? Not sure what to do next ?
I have no option to test a more recent c++ version but I'm also having difficulties comprehending how the compiler could be responsible here.
Any guidance appreciated.
Delphi tag added because of VCL overlap between c++ Builder and Delphi
On Windows Vista and later, IF AND ONLY IF all of these conditions are met:
the global Dialogs::UseLatestCommonDialogs variable is true
and the TSaveDialog::Template property is NULL
and the TSaveDialog::OnIncludeItem, TSaveDialog::OnClose, and TSaveDialog::OnShow events have no handlers assigned
Then TSaveDialog will internally use the Win32 IFileSaveDialog interface, where the ofAllowMultiSelect option will be mapped to that dialog's FOS_ALLOWMULTISELECT option, which is NOT SUPPORTED by IFileSaveDialog, only by IFileOpenDialog, per the documentation:
FOS_ALLOWMULTISELECT
Enables the user to select multiple items in the open dialog. Note that when this flag is set, the IFileOpenDialog interface must be used to retrieve those items.
If the above 3 conditions are not satisfied, then TSaveDialog will internally use the Win32 GetSaveFileName() function instead, where the ofAllowMultiSelect option will be mapped to that dialog's OFN_ALLOWMULTISELECT option, which IS SUPPORTED by GetSaveFileName() 1.
That is why you are seeing behavioral differences when running your app on Windows XP vs Windows 10.
So, if you want the old TSaveDialog behavior on newer Windows versions, you need to make sure at least 1 of those 3 conditions is not satisfied. For instance, by setting UseLatestCommonDialogs=false before calling SaveDialog->Execute(), or by assigning an (empty) event handler to one of the OnIncludeItem/OnClose/OnShow events.
Or, you could simply call GetSaveFileName() directly, instead of using TSaveDialog at all.
1: However, just note that on Vista+, GetSaveFileName() is just a wrapper for IFileSaveDialog, and is provided only for backwards compatibility. So, you still might not get the exact behavior you want even if you did use GetSaveFileName() on Windows 10.
On a side note: this code does not work the way you think it does:
SaveDialog->Options.Clear();
SaveDialog->Options << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect;
The Options property is not actually updated! In both statements, the Options property is read from, returning a temporary TOpenOptions, which you are then modifying, but not assigning back to the Options property. IOW, the code is effectively doing the following:
TOpenOptions temp1 = SaveDialog->Options;
temp1.Clear();
TOpenOptions temp2 = SaveDialog->Options;
temp2 << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect;
So, to update the Options property correctly, use this instead:
SaveDialog->Options = TOpenOptions() << ofHideReadOnly << ofEnableSizing << ofAllowMultiSelect;

Why would a WMI query fail sometimes, but not others?

I run the same code from two different locations in my application. I know it is the same code, because it is in a class and that class only has one publicly facing function. Both places call the function with the same arguments and both are running in the UI thread.
The function does a search for a particular printer by name using an asynchronous WMI query-->
var searcher =
new ManagementObjectSearcher(
"SELECT * from Win32_Printer WHERE Name LIKE '%ZDesigner GX430t'");
// Create an observer to trigger a callback when the search is completed.
var watcher = new ManagementOperationObserver();
watcher.Completed += PrinterSearchCompleted;
watcher.ObjectReady += PrinterSearchReady;
// Look for the printer
_printerFound = false;
_searchCompleted = false;
searcher.Get(watcher);
The problem I am having is that the ObjectReady event is not triggered when I run it from one location and when I run it from another, it get's triggered all the time.
Also, another problem is that this seems to be computer specific; some of the computers I run this on work just fine, others exhibit the problem I described above.
Any ideas what I should be looking for?
Couple of things to try:
Check if WMI service is running on all the computers.
Restart WMI service on the computers where it is not working.
You may find this article useful.
If its a Windows 7 or Windows Server 2008 R2 server, WMI has a memory leak problem. Check this.

Windows Shell and Citrix

I have this line of code in my Delphi app:
sh := CoShellWindows.Create;
When run through a Citrix session, this raises an exception "Not enough storage is available to complete this operation."
Can someone confirm my suspicion that I can't access this through Citrix? I'm running in Seamless mode if that makes any difference. Maybe there's something I need to change on the published icon to make it work?
I am guessing that there is no "Shell" in Citrix to create.
Thanks
EDIT
The CoShellWindows is simply a class which creates an object which implements the IShellWindows interface. This interface is then used to iterate through it's items looking for an instance of Internet Explorer (or more specifically, an item which implements the IWebBrowser2 interface).
There are a few other use case scenarios using the CoShellWindows, but all ultimately are used to interact with the IWebBrowser2 interface (Internet Explorer 8). My requirement is to obtain this IWebBrowser2 object.
The call, behind the scenes is calling the Windows API CoCreateInstance with the following parameters:
rclsid = {9BA05972-F6A8-11CF-A442-00A0C90A8F39} (CLSID of
IShellWindows)
pUnkOuter = null (nil)
dwClsContext = CLSCTX_ALL (I've tried various combinations of these
flags)
riid = {85CB6900-4D95-11CF-960C-0080C7F4EE85} (IID of IShellWindows)
ppv = a variable declared as type IShellWindows
eg:CoCreateInstance(CLASS_ShellWindows, nil, CLSCTX_ALL, IID_IShellWindows, sh)
Your exception "Not enough storage is available to complete this operation." should really read "Shell does not exist so no instance can be created"
Basically you are correct in your assumption that there is no shell to create in Citrix.
What are you using the shell for? as if you provide more information we may well be able to offer a full work around.

How to read the current machine NTFS settings?

Before inserting filestream data I'd like to check the following NTFS settings:
1) 8.3 naming status (this is disabled by using fsutil behavior set disable8dot3 1)
2) last access status (this is disabled by using fsutil behavior set disablelastaccess 1)
3) cluster size (this is set with format F: /FS:NTFS /V:MyFILESTREAMContainer /A:64K)
The filestream recomendation is to disable (1) and (2) and to set (3) at 64kb.
But before setting this I'd like to know the existing settings. How do I check this? Answer can be in Delphi but not necessarly.
The GetDiskFreeSpace Windows API call returns the sector_per_cluster and bytes_per_sector values. I think this function should be in Windows unit.
You can read the registry for points 1 and 2 (using xp_regread in SQL)
Number 3 is not essential but helps and has been SQL Server best practice for a decade or more. You'd have to use sp_OA% or a CLR function to read this in SQL.

Resources