Want to set scanning options programmatically (Leadtools SDK) - c#

When I scan document via Leadtools SDK using sample code that provided by Leadtools. It show me scanning options form. I don't want to show this scanning options(form) to user.
How can I hide this and set scanning options programmatically? I have gone through leadtools documentations and example but couldn't find.
Sceenshot of sanning options is attached Scanning Options
WiaAcquireFlags flags = WiaAcquireFlags.None;
bool showProgress = true;
_progressDlg = new ProgressForm("Transferring", "", 100);
_wiaAcquiring = true;
if (_showUserInterface)
{
flags = WiaAcquireFlags.UseCommonUI | WiaAcquireFlags.ShowUserInterface;
}
else
{
if (SelectAcquireSource() != System.Windows.Forms.DialogResult.OK)
{
_wiaAcquiring = false;
return;
}
}
if (_showUserInterface && _wiaVersion == WiaVersion.Version2)
showProgress = false;
if (showProgress)
_progressDlg.Show();
_wiaSession.AcquireOptions = _wiaAcquireOptions;
_transferMode = (_wiaProperties.DataTransfer.TransferMode == WiaTransferMode.None) ? WiaTransferMode.Memory : _wiaProperties.DataTransfer.TransferMode;

According to the documentation, if you do not want to show the user interface of the scanner, you should not pass the WiaAcquireFlags for ShowUserInterface and instead use WiaAcquireFlags.None.
https://www.leadtools.com/help/leadtools/v19/dh/wa/wiaacquireflags.html
In the code you pasted above, you need to ensure that _showUserInterface is set to false.
If you want to set the properties programmatically, you can use the WiaSession.SetPropertyXXX() methods. For example, if your device (scanner) supports setting the X and Y resolution values, you can do it using code like this:
_wiaSession.SetPropertyLong(_selectedWiaItem, null, WiaPropertyId.ScannerItemXRes, 300);
_wiaSession.SetPropertyLong(_selectedWiaItem, null, WiaPropertyId.ScannerItemYRes, 300);
https://www.leadtools.com/help/leadtools/v19/dh/wa/wiasession-setpropertylong.html

Related

C# How to get the AD user cannot change the password property from LDAP attribute userAccountControl?

I am trying to get the user account control properties using library Novell.Directory.Ldap in ASP .NET Core 5. When I search the users attributes I found the attribute name userAccountControl which is set to some number. After searching solution I am able to find:
bool isUserActive = false;
bool userMustChangePassword = false;
bool passwordNeverExpires = false;
bool passwordCannotBeChanged = false;
var flags = Convert.ToInt32(attributeSet.GetAttribute("userAccountControl").StringValue);
isUserActive = !Convert.ToBoolean(flags & 0x0002); //1. checks if user is enabled
if ((flags == 66048)) //65536+512
{
passwordNeverExpires = true; //2. Password never expires property
}
long value = Convert.ToInt64(attributeSet.GetAttribute("pwdLastSet").StringValue);
if (value == 0)
{
userMustChangePassword = true; //3. User must change password at next login
}
But I am not able to figure out how to get the User cannot change password and if the account is locked properties? Or how can I compare the binary value like 0x0040? Please help
Edit:
I tried the steps given by #Gabriel Luci in https://www.gabescode.com/active-directory/2019/07/25/nt-security-descriptors.html and tried following code:
var act = attributeSet.GetAttribute("nTSecurityDescriptor").ByteValue;
ADsSecurityUtility secUtility = new ADsSecurityUtility();
IADsSecurityDescriptor convertAttrToSD = (IADsSecurityDescriptor)secUtility.ConvertSecurityDescriptor(act, (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_RAW, (int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID);
var byteArray = (byte[])secUtility.ConvertSecurityDescriptor(
convertAttrToSD,
(int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_IID,
(int)ADS_SD_FORMAT_ENUM.ADS_SD_FORMAT_RAW
);
var security = new CommonSecurityDescriptor(true, true, byteArray, 0);
If I check the security it shows
I am not getting where to look user cannot change the password settings?
Edit 2:
According to #Gabriel Luci updated answer, it worked for me like this:
var constraints = new LdapSearchConstraints();
constraints.SetControls(new LdapControl("1.2.840.113556.1.4.801", true, new byte[] { 48, 3, 2, 1, 7 }));
var getNtSecurityByteValue=attributeSet.GetAttribute("nTSecurityDescriptor").ByteValue;
var security = new CommonSecurityDescriptor(true, true, getNtSecurityByteValue, 0);
var self = new SecurityIdentifier(WellKnownSidType.SelfSid, null);
var userChangePassword = new Guid("AB721A53-1E2F-11D0-9819-00AA0040529B");
foreach (var ace in security.DiscretionaryAcl)
{
if(ace.GetType().Name == "ObjectAce")
{
ObjectAce objAce = (ObjectAce)ace;
if (objAce.AceType == AceType.AccessDeniedObject && objAce.SecurityIdentifier == self && objAce.ObjectAceType == userChangePassword)
{
cannotChangePassword = true;
break;
}
}
}
The userAccountControl value is a bit flag, meaning that every bit in the binary representation of the number is an "on" or "off" depending on if it's a 1 or 0. So the decimal value is meaningless.
You are already checking the value properly when you're checking if it's enabled:
isUserActive = !Convert.ToBoolean(flags & 0x0002); //1. checks if user is enabled
Likewise, you should do the same when checking any of the other flags. The value of each is listed in the documentation.
When you're checking if the password is set to never expire, you're comparing the decimal value, which won't always give you a correct answer. Instead, check the bit value:
passwordNeverExpires = Convert.ToBoolean(flags & 0x10000);
Similar for account is locked:
var accountLocked = Convert.ToBoolean(flags & 0x0010);
For the user cannot change password setting, unfortunately that's more difficult and requires reading the permissions on the user account, which I have never done using the Novell.Directory.Ldap library. But I can try to point you in the right direction.
The account permissions are in the nTSecurityDescriptor attribute. Read this issue about how to get the byte array from that attribute: How to read/set NT-Security-Descriptor attributes?
I wrote an article about how to get the byte array into a usable format: Active Directory: Handling NT Security Descriptor attributes.
Then you'll be looking for two permissions that get added when the 'User cannot change password' checkbox is checked:
Deny Change Password to 'Everyone'
Deny Change Password to 'SELF'
You can probably get away with only looking for #2.
Update: I finally tried this out for myself. I had never used the Novell.Directory.Ldap library before, so this was new to me.
With the help of this answer, I figured out that you need to set an LDAP control for it to return the nTSecurityDescriptor attribute at all:
var constraints = new LdapSearchConstraints();
constraints.SetControls(new LdapControl("1.2.840.113556.1.4.801", true
, new byte[] {48, 3, 2, 1, 7}));
Once you retrieve the object, you can check the permissions like this:
var byteValue = attributeSet.GetAttribute("nTSecurityDescriptor").ByteValue;
var security = new CommonSecurityDescriptor(true, true, byteValue, 0);
var self = new SecurityIdentifier(WellKnownSidType.SelfSid, null);
var userChangePassword = new Guid("AB721A53-1E2F-11D0-9819-00AA0040529B");
var cannotChangePassword = false;
foreach (var ace in (security.DiscretionaryAcl)) {
if (ace is ObjectAce objAce && objAce.AceType == AceType.AccessDeniedObject
&& objAce.SecurityIdentifier == self && objAce.ObjectAceType == userChangePassword) {
cannotChangePassword = true;
break;
}
}
The GUID of the User-Change-Password permission is taken from the Control Access Rights documentation.
Notice that you don't need to use IADsSecurityDescriptor, and thus you don't need a reference to Interop.ActiveDs. This is because we're given the value as a byte array already.

How to point to the correct Store in Outlook automation by C#?

I have a lot of VBA automation that interlinks an Outlook and Word solution; it is fine, but time is inexorable... so, I'm start to decorating and extending that old solution, wraping it with C#/VS2017.
Through a conventional Winform I can choose my patients, and from this action I do a lot of actions, including open the correct Outlook contact; that's the problem, because I can't get the correct Store; the patients.pst, depending on the machine, may be the 1st, 2nd, 3rd...
In VBA I do this:
WhichStoreNameToPointAt="patients"
Set myNamespace = myolApp.GetNamespace("MAPI")
For i = 1 To myNamespace.Stores.Count Step 1
If myNamespace.Stores.item(i).DisplayName = WhichStoreNameToPointAt Then
intOutlookItemStore = i
End if
End If
Set myFolderPatients = myNamespace.Stores.item(intOutlookItemStore).GetDefaultFolder(olFolderContacts)
And it always functions like a charm.
In C# I tried a lot of variations, and could not point to the correct store:
public void OpenPatientContact(string patientName)
{
Outlook.Store whichStore = null;
Outlook.NameSpace nameSpace = OlkApp.Session;
int i = 1;
foreach (Outlook.Folder folder in nameSpace.Folders)
{
bool p = false;
if (whichStoreNameToPointAt == folder.Name)
{
p = true;
whichStore = folder.Store;
//Correct Store selected; I can tell because of this watch:
//whichStore.displayname == whichStoreNameToPointAt
}
i++;
if (p)
break;
}
var contactItemsOlk = whichStore.Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderContacts).Items;
// The problem is below; always the first Store
Outlook.ContactItem contact = (Outlook.ContactItem)contactItemsOlk
.Find(string.Format("[FullName]='{0}'", patientName)); //[1];
if (contact != null)
{
contact.Display(true);
}
else
{
MessageBox.Show("The contact information was not found.");
}
}
Unfortunately, it keeps pointing ever to the same first Store, the one that has no patients...
If I change the Store order I can get past this and test other stuff, but of course it is not the right way.
Any other heads/eyes to see the light?
TIA
While seated writing the question, looking at a yellow rubber duck - and a lot of other stuff that belongs to my 1 yo daughter ;), I realized that whichStore.Session.GetDefaultFolder is a little strange in this context. I only changed this
var contactItemsOlk = whichStore.Session.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderContacts).Items;
To that:
var contactItemsOlk = whichStore.GetDefaultFolder
(Outlook.OlDefaultFolders.olFolderContacts).Items;
Voilá! Magic happens with C# too!
Session returns the default NameSpace object for the current session.
PS: yellow rubber duck; guys of The Pragmatic Programmer really knows some secrets and tricks ;)
Thanks Thomas and Hunt!

CefSharp ignores Preferences set with RequestContext (Spellcheck)

I try to enable spell check for the CefSharp Chromium embedded browser (v3.3396.1786 installed with NuGet) and the CefSharp.WPF component (v67). I can get spell check to work with a single language but I'm not able to change the dictionary for spellchecking at runtime. I tried the examples shown and linked on CefSharps github page but without success.
My CefSharp browser always uses the the Locale to determine the language to use for spell checking no matter what I set with RequestContext.SetPreference()
This is my code which initializes Cef:
public static void Initialize()
{
var settings = new CefSettings
{
BrowserSubprocessPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
Environment.Is64BitProcess ? "x64" : "x86",
"CefSharp.BrowserSubprocess.exe"),
Locale = "de-DE",
RemoteDebuggingPort = 8088,
};
// Set BrowserSubProcessPath based on app bitness at runtime
// Make sure you set performDependencyCheck false
Cef.Initialize
(
settings,
performDependencyCheck: false,
browserProcessHandler: null
);
CefSharpSettings.LegacyJavascriptBindingEnabled = true;
}
The actual browser is set up and created in another method:
private void create_web_browser()
{
current_web_browser = new ChromiumWebBrowser
{
Visibility = Visibility.Hidden,
BrowserSettings = new BrowserSettings
{
FileAccessFromFileUrls = CefState.Enabled,
UniversalAccessFromFileUrls = CefState.Enabled,
Javascript = CefState.Enabled,
ImageLoading = CefState.Enabled,
JavascriptAccessClipboard = CefState.Enabled,
JavascriptCloseWindows = CefState.Enabled,
JavascriptDomPaste = CefState.Enabled
}
};
current_helper = new ChromiumObjectForScriptingHelper(web_browser_ready_async, current_web_browser);
if (ToolbarConfig != null)
{
current_helper.SetToolbarConfig(ToolbarConfig);
}
current_web_browser.RegisterJsObject("callbackObj", current_helper);
var cur_dir = Directory.GetCurrentDirectory();
var url = $"file://{cur_dir}/ckeditor/editor.html";
current_web_browser.Address = url;
current_web_browser.RequestContext = new RequestContext();
current_web_browser.RequestContext.SetPreference("browser.enable_spellchecking", true, out _);
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<string> { "en-US" }, out _);
grid.Children.Add(current_web_browser);
}
An additional method is used to enable the user to change language later:
public void SetSpellcheck(Spellcheck language)
{
if (language == Spellcheck.None) return;
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<string> { get_locale_for_language(language) }, out _);
}
As you can see I try to set the spell checking settings but no matter what I set there, it has no effect. I could set enable_spellcheckto false and it still checks the spelling and the dictionaries I set are also ignored. Instead of what I put in dictionaries, the language previously set in Locale will be used. (I checked the out variable but there were no errors)
I also tried using the global RequestContext but with no success.
Apparently other people got it to work somehow so I'm feeling like I miss something important here, or doing something completely stupid.
Another thing is that, if I use GetAllPreferences(true), to get a list of all the settings with defaults, I just get null.
Thanks to #amaitlands's comments I now know that the issue was that I was setting the preferences in the wrong thread. I had the misconception that CefSharp was running in my applications UI-Thread, when it actually was running in its own.
The solution is to use Cef.UIThreadTaskFactory.StartNew() to run the code inside of the CefSharp UI-Thread
Cef.UIThreadTaskFactory.StartNew(delegate
{
current_web_browser.RequestContext.SetPreference("browser.enable_spellchecking", true, out _);
current_web_browser.RequestContext.SetPreference("spellcheck.dictionaries", new List<object> { "en-US" }, out _);
});
I also had to change the type of the List<> to object since I'm using an older version of CefSharp.WPF otherwise I'd get a Trying to set a preference of type LIST to value of type NULL error.

How to dynamically add watermark to report in Stimulsoft

I would like to dynamically add watermark to a report that is generated in Stimulsoft. The watermark can not be hard-coded and only appear if the report was generated in TEST environment.
I have a variable that checks if the report was created in test environment:
isTestEnv
Which means that if the watermark was added to the page the old fashioned way I would use:
if(isTestEnv == true) {
Page1.Watermark.Enabled = true;
} else {
Page1.Watermark.Enabled = false;
}
But this is not the case. I have to add the watermark when generating the report. Does anyone know how to?
The text is same on all pages it simply says "TEST". But how to push that into a report is the mystery.
you can use this code and set your water mark image in your report
Stimulsoft.Base.StiLicense.loadFromFile("../license.key");
var options = new Stimulsoft.Viewer.StiViewerOptions({showTooltips:false});
var viewer = new Stimulsoft.Viewer.StiViewer(options, "StiViewer", false);
var report = new Stimulsoft.Report.StiReport({isAsyncMode: true});
report.loadFile("Backgroundimg.mrt");
var page = report.pages.getByIndex(0);
page.watermark.image = Stimulsoft.System.Drawing.Image.fromFile('test.jpg');
page.watermark.aspectRatio = true;
page.watermark.imageStretch = true;
page.watermark.imageShowBehind= true;
report.renderAsync(function () {
viewer.report = report;
viewer.renderHtml("viewerContent");
});
You can set the report page watermark to some Report variable at design time and in your code set the value for the report variable.
Something like this:
StiReport report = new StiReport();
report.Load("REPORT_TEMPLATE_PATH");
//You can check if this variable exists or not using an if condition
report.Dictionary.Variables["WATERMARK_VARIABLE_NAME"] = "YOUR_TEXT";
report.Show();//or report.ShowWithWpf();

How make a click in button with windows AutomationElement

Following this article
http://www.codeproject.com/Articles/141842/Automate-your-UI-using-Microsoft-Automation-Framew
I'm trying to open an application and press a button. This is all that I want.
public RecordProgram()
{
ProcessStartInfo psi = new ProcessStartInfo(#"C:\MouseController.exe", #"C:\test1.mcd");
psi.UseShellExecute = false;
_calculatorProcess = Process.Start(psi);
int ct = 0;
do
{
_calculatorAutomationElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "MouseController (1,0x)"));
++ct;
Thread.Sleep(100);
}
while (_calculatorAutomationElement == null && ct < 50);
if (_calculatorAutomationElement == null)
{
throw new InvalidOperationException("Calculator must be running");
}
_resultTextBoxAutomationElement = _calculatorAutomationElement.FindFirst(TreeScope.Element, new PropertyCondition(AutomationElement.AutomationIdProperty, "920388"));
if (_resultTextBoxAutomationElement == null)
{
throw new InvalidOperationException("Could not find result box");
}
GetInvokePattern(GetFunctionButton(Functions.Clear)).Invoke();
}
The prograns run and open the executable with my file load But _resultTextBoxAutomationElement returns null value.
_resultTextBoxAutomationElement = _calculatorAutomationElement.FindFirst(TreeScope.Element, new PropertyCondition(AutomationElement.AutomationIdProperty, "920388"));
Shouldn't the call to _calculatorAutomationElement.FindFirst() be passing in TreeScope.Children instead of TreeScope.Element? (Assuming the button element you're after is a direct child of the app window element.) By passing in TreeScope.Element as you are doing, UIA will only look at the _calculatorAutomationElement itself for an element with an AutomationId of 920388.
Thanks,
Guy
To illustrate my comment above which mentioned the Run dlg's Browse button as an example of accessing a Win32 button through its AutomationId, I've just written the code below to access the Browse button. The code is using a managed wrapper around the Windows UIA API, that I'd generated using the tlbimp.exe tool, but I expect taking a similar approach with the .NET UIA API would work fine too.
So for the MouseController UI shown above, try changing the line to...
_resultTextBoxAutomationElement = _calculatorAutomationElement.FindFirst(
TreeScope.Children, new PropertyCondition
(AutomationElement.AutomationIdProperty, "2296138"));
(I'm assuming that the Inspect SDK tool does show the AutomationId of the "start playback" button is "2296138".)
Thanks,
Guy
IUIAutomation uiAutomation = new CUIAutomation();
IUIAutomationElement rootElement = uiAutomation.GetRootElement();
int propertyIdName = 30005; // UIA_NamePropertyId
// First find the Run dlg, which is a direct child of the root element.
// For this test, assume there's only one element whose title is "Run"
// beneath the root. Note! This only works in English UI.
IUIAutomationCondition conditionName =
uiAutomation.CreatePropertyCondition(
propertyIdName, "Run");
IUIAutomationElement wndElement = rootElement.FindFirst(
TreeScope.TreeScope_Children, conditionName);
if (wndElement != null)
{
// Ok, we have the Run dialog. Now find the Browse button through its AutomationId.
int propertyAutomationId = 30011; // UIA_AutomationIdPropertyId
// Using the Inspect SDK tool, I could see that the AutomationId of
// the Browse button is "12288".
IUIAutomationCondition conditionAutomationId =
uiAutomation.CreatePropertyCondition(
propertyAutomationId, "12288");
// Get the name of the button cached when we find the button, so that
// we don't have to make a cross-process call later to get the name.
IUIAutomationCacheRequest cacheRequestName = uiAutomation.CreateCacheRequest();
cacheRequestName.AddProperty(propertyIdName);
IUIAutomationElement btnElement = wndElement.FindFirstBuildCache(
TreeScope.TreeScope_Children, conditionAutomationId, cacheRequestName);
if (btnElement != null)
{
// Let's see the name now...
MessageBox.Show(btnElement.CachedName);
}
}

Categories